/*
* 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.
*
* Contributions from 2013-2017 where performed either by US government
* employees, or under US Veterans Health Administration contracts.
*
* US Veterans Health Administration contributions by government employees
* are work of the U.S. Government and are not subject to copyright
* protection in the United States. Portions contributed by government
* employees are USGovWork (17USC ยง105). Not subject to copyright.
*
* Contribution by contractors to the US Veterans Health Administration
* during this period are contractually contributed under the
* Apache License, Version 2.0.
*
* See: https://www.usa.gov/government-works
*
* Contributions prior to 2013:
*
* Copyright (C) International Health Terminology Standards Development Organisation.
* Licensed under the Apache License, Version 2.0.
*
*/
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package sh.isaac.provider.taxonomy;
//~--- JDK imports ------------------------------------------------------------
import java.util.Optional;
import java.util.stream.IntStream;
//~--- non-JDK imports --------------------------------------------------------
import sh.isaac.api.collections.ConceptSequenceSet;
import sh.isaac.api.coordinate.StampCoordinate;
import sh.isaac.api.coordinate.TaxonomyCoordinate;
import sh.isaac.model.WaitFreeComparable;
import sh.isaac.model.waitfree.CasSequenceObjectMap;
//~--- classes ----------------------------------------------------------------
/**
* The Class TaxonomyRecordPrimitive.
*
* @author kec
*/
public class TaxonomyRecordPrimitive
implements WaitFreeComparable {
/** The Constant SEQUENCE_BIT_MASK. */
public static final int SEQUENCE_BIT_MASK = 0x00FFFFFF;
/** The Constant STAMP_BIT_MASK. */
public static final int STAMP_BIT_MASK = 0x00FFFFFF;
/** The Constant LENGTH_BIT_MASK. */
public static final int LENGTH_BIT_MASK = 0xFF000000;
/** The Constant FLAGS_BIT_MASK. */
public static final int FLAGS_BIT_MASK = 0xFF000000;
//~--- fields --------------------------------------------------------------
/** The unpacked. */
transient TaxonomyRecordUnpacked unpacked = null;
/** The write sequence. */
int writeSequence;
/** The taxonomy data. */
int[] taxonomyData;
//~--- constructors --------------------------------------------------------
/**
* Instantiates a new taxonomy record primitive.
*/
public TaxonomyRecordPrimitive() {
this.taxonomyData = new int[0];
}
/**
* Instantiates a new taxonomy record primitive.
*
* @param taxonomyData the taxonomy data
* @param writeSequence the write sequence
*/
public TaxonomyRecordPrimitive(int[] taxonomyData, int writeSequence) {
this.taxonomyData = taxonomyData;
this.writeSequence = writeSequence;
}
//~--- methods -------------------------------------------------------------
/**
* Adds the concept sequence stamp record.
*
* @param conceptSequenceStampRecord the concept sequence stamp record
*/
public void addConceptSequenceStampRecord(int[] conceptSequenceStampRecord) {
conceptSequenceStampRecord[0] = conceptSequenceStampRecord[0] + (conceptSequenceStampRecord.length << 24);
}
/**
* Concept satisfies stamp.
*
* @param conceptSequence the concept sequence
* @param stampCoordinate the stamp coordinate
* @return true, if successful
*/
public boolean conceptSatisfiesStamp(int conceptSequence, StampCoordinate stampCoordinate) {
return getTaxonomyRecordUnpacked().conceptSatisfiesStamp(conceptSequence, stampCoordinate);
}
/**
* Contains sequence via type.
*
* @param conceptSequence the concept sequence
* @param typeSequenceSet the type sequence set
* @param flags the flags
* @return true, if successful
*/
public boolean containsSequenceViaType(int conceptSequence, ConceptSequenceSet typeSequenceSet, int flags) {
return getTaxonomyRecordUnpacked().containsConceptSequenceViaType(conceptSequence, typeSequenceSet, flags);
}
/**
* Contains sequence via type.
*
* @param conceptSequence the concept sequence
* @param typeSequenceSet the type sequence set
* @param tc the tc
* @return true, if successful
*/
public boolean containsSequenceViaType(int conceptSequence,
ConceptSequenceSet typeSequenceSet,
TaxonomyCoordinate tc) {
return getTaxonomyRecordUnpacked().containsConceptSequenceViaType(conceptSequence, typeSequenceSet, tc);
}
/**
* Contains sequence via type.
*
* @param conceptSequence the concept sequence
* @param typeSequence the type sequence
* @param tc the tc
* @return true, if successful
*/
public boolean containsSequenceViaType(int conceptSequence, int typeSequence, TaxonomyCoordinate tc) {
return getTaxonomyRecordUnpacked().containsConceptSequenceViaType(conceptSequence, typeSequence, tc);
}
/**
* Contains sequence via type.
*
* @param conceptSequence the concept sequence
* @param typeSequenceSet the type sequence set
* @param tc the tc
* @param flags the flags
* @return true, if successful
*/
public boolean containsSequenceViaType(int conceptSequence,
ConceptSequenceSet typeSequenceSet,
TaxonomyCoordinate tc,
int flags) {
return getTaxonomyRecordUnpacked().containsConceptSequenceViaType(conceptSequence, typeSequenceSet, tc, flags);
}
/**
* Contains sequence via type.
*
* @param conceptSequence the concept sequence
* @param typeSequence the type sequence
* @param tc the tc
* @param flags the flags
* @return true, if successful
*/
public boolean containsSequenceViaType(int conceptSequence, int typeSequence, TaxonomyCoordinate tc, int flags) {
return getTaxonomyRecordUnpacked().containsConceptSequenceViaType(conceptSequence, typeSequence, tc, flags);
}
/**
* Contains sequence via type with flags.
*
* @param conceptSequence the concept sequence
* @param typeSequence the type sequence
* @param flags the flags
* @return true, if successful
*/
public boolean containsSequenceViaTypeWithFlags(int conceptSequence, int typeSequence, int flags) {
return getTaxonomyRecordUnpacked().containsSequenceViaTypeWithFlags(conceptSequence, typeSequence, flags);
}
/**
* Inferred flag set.
*
* @param index the index
* @return true, if successful
*/
public boolean inferredFlagSet(int index) {
return (this.taxonomyData[index] & TaxonomyFlags.INFERRED.bits) == TaxonomyFlags.INFERRED.bits;
}
/**
* Next record index.
*
* @param index the index
* @return the int
*/
public int nextRecordIndex(int index) {
return this.taxonomyData[index] >>> 24;
}
/**
* Stated flag set.
*
* @param index the index
* @return true, if successful
*/
public boolean statedFlagSet(int index) {
return (this.taxonomyData[index] & TaxonomyFlags.STATED.bits) == TaxonomyFlags.STATED.bits;
}
/**
* To string.
*
* @return the string
*/
@Override
public String toString() {
return getTaxonomyRecordUnpacked().toString();
}
/**
* Unpack.
*
* @return the taxonomy record unpacked
*/
public TaxonomyRecordUnpacked unpack() {
return new TaxonomyRecordUnpacked(this.taxonomyData);
}
//~--- get methods ---------------------------------------------------------
/**
* Gets the array.
*
* @return the array
*/
public int[] getArray() {
if (this.unpacked != null) {
this.taxonomyData = this.unpacked.pack();
}
return this.taxonomyData;
}
/**
* Checks if concept active.
*
* @param conceptSequence the concept sequence
* @param stampCoordinate the stamp coordinate
* @return true, if concept active
*/
public boolean isConceptActive(int conceptSequence, StampCoordinate stampCoordinate) {
return getTaxonomyRecordUnpacked().conceptSatisfiesStamp(conceptSequence, stampCoordinate);
}
/**
* Checks if concept active.
*
* @param conceptSequence the concept sequence
* @param taxonomyMap the taxonomy map
* @param sc the sc
* @return true, if concept active
*/
public static boolean isConceptActive(int conceptSequence,
CasSequenceObjectMap<TaxonomyRecordPrimitive> taxonomyMap,
StampCoordinate sc) {
final Optional<TaxonomyRecordPrimitive> optionalRecord = taxonomyMap.get(conceptSequence);
if (optionalRecord.isPresent()) {
final TaxonomyRecordPrimitive record = optionalRecord.get();
if (record.isConceptActive(conceptSequence, sc)) {
return true;
}
}
return false;
}
/**
* Gets the concept sequence.
*
* @param index the index
* @return the concept sequence
*/
public int getConceptSequence(int index) {
return this.taxonomyData[index] & SEQUENCE_BIT_MASK;
}
/**
* Gets the concept sequence index.
*
* @param conceptSequence the concept sequence
* @return the concept sequence index
*/
public int getConceptSequenceIndex(int conceptSequence) {
throw new UnsupportedOperationException();
}
//~--- set methods ---------------------------------------------------------
/**
* Set concept sequence stamp record length.
*
* @param index the index
* @param length the length
*/
public void setConceptSequenceStampRecordLength(int index, int length) {
this.taxonomyData[index] = this.taxonomyData[index] & SEQUENCE_BIT_MASK;
length = length << 24;
this.taxonomyData[index] = this.taxonomyData[index] + length;
}
//~--- get methods ---------------------------------------------------------
/**
* Gets the destination sequences.
*
* @return the destination sequences
*/
public IntStream getDestinationSequences() {
return getTaxonomyRecordUnpacked().getDestinationConceptSequences();
}
/**
* Gets the destination sequences not of type.
*
* @param typeSequenceSet the type sequence set
* @param tc the tc
* @return the destination sequences not of type
*/
public IntStream getDestinationSequencesNotOfType(ConceptSequenceSet typeSequenceSet, TaxonomyCoordinate tc) {
return getTaxonomyRecordUnpacked().getDestinationConceptSequencesNotOfType(typeSequenceSet, tc);
}
/**
* Gets the destination sequences of type.
*
* @param typeSequenceSet the type sequence set
* @return the destination sequences of type
*/
public IntStream getDestinationSequencesOfType(ConceptSequenceSet typeSequenceSet) {
return getTaxonomyRecordUnpacked().getDestinationConceptSequencesOfType(typeSequenceSet);
}
/**
* Gets the destination sequences of type.
*
* @param typeSequenceSet the type sequence set
* @param tc the tc
* @return the destination sequences of type
*/
public IntStream getDestinationSequencesOfType(ConceptSequenceSet typeSequenceSet, TaxonomyCoordinate tc) {
return getTaxonomyRecordUnpacked().getDestinationConceptSequencesOfType(typeSequenceSet, tc);
}
/**
* Gets the if active via type.
*
* @param conceptSequence the concept sequence
* @param typeSequence the type sequence
* @param taxonomyMap the taxonomy map
* @param vp the vp
* @param flags the flags
* @return the if active via type
*/
public static Optional<TaxonomyRecordPrimitive> getIfActiveViaType(int conceptSequence,
int typeSequence,
CasSequenceObjectMap<TaxonomyRecordPrimitive> taxonomyMap,
TaxonomyCoordinate vp,
int flags) {
final Optional<TaxonomyRecordPrimitive> optionalRecord = taxonomyMap.get(conceptSequence);
if (optionalRecord.isPresent()) {
final TaxonomyRecordPrimitive record = optionalRecord.get();
if (record.containsSequenceViaType(conceptSequence, typeSequence, vp, flags)) {
return optionalRecord;
}
}
return Optional.empty();
}
/**
* Gets the if concept active.
*
* @param conceptSequence the concept sequence
* @param taxonomyMap the taxonomy map
* @param vp the vp
* @return the if concept active
*/
public static Optional<TaxonomyRecordPrimitive> getIfConceptActive(int conceptSequence,
CasSequenceObjectMap<TaxonomyRecordPrimitive> taxonomyMap,
TaxonomyCoordinate vp) {
final Optional<TaxonomyRecordPrimitive> optionalRecord = taxonomyMap.get(conceptSequence);
if (optionalRecord.isPresent()) {
final TaxonomyRecordPrimitive record = optionalRecord.get();
if (record.containsSequenceViaType(conceptSequence, conceptSequence, vp, TaxonomyFlags.CONCEPT_STATUS.bits)) {
return optionalRecord;
}
}
return Optional.empty();
}
/**
* Gets the parent sequences.
*
* @return the parent sequences
*/
public IntStream getParentSequences() {
return getTaxonomyRecordUnpacked().getParentConceptSequences();
}
/**
* Gets the parent sequences.
*
* @param tc the tc
* @return the parent sequences
*/
public IntStream getParentSequences(TaxonomyCoordinate tc) {
return getTaxonomyRecordUnpacked().getConceptSequencesForType(tc.getIsaConceptSequence(), tc);
}
//~--- set methods ---------------------------------------------------------
/**
* Set sequence.
*
* @param index the index
* @param sequence the sequence
*/
public void setSequence(int index, int sequence) {
this.taxonomyData[index] = sequence;
}
//~--- get methods ---------------------------------------------------------
/**
* Gets the stamp.
*
* @param index the index
* @return the stamp
*/
public int getStamp(int index) {
// clear any flag bits
return this.taxonomyData[index] & SEQUENCE_BIT_MASK;
}
//~--- set methods ---------------------------------------------------------
/**
* Set stamp and flags.
*
* @param index the index
* @param stamp the stamp
* @param flags the flags
*/
public void setStampAndFlags(int index, int stamp, TaxonomyFlags... flags) {
this.taxonomyData[index] = stamp;
for (final TaxonomyFlags flag: flags) {
this.taxonomyData[index] = this.taxonomyData[index] | flag.bits;
}
}
//~--- get methods ---------------------------------------------------------
/**
* Gets the taxonomy data.
*
* @return the taxonomy data
*/
public int[] getTaxonomyData() {
return this.taxonomyData;
}
/**
* Gets the taxonomy record unpacked.
*
* @return the taxonomy record unpacked
*/
public TaxonomyRecordUnpacked getTaxonomyRecordUnpacked() {
if (this.unpacked != null) {
return this.unpacked;
}
this.unpacked = new TaxonomyRecordUnpacked(this.taxonomyData);
return this.unpacked;
}
/**
* Gets the types for relationship.
*
* @param destinationId the destination id
* @param tc the tc
* @return the types for relationship
*/
public IntStream getTypesForRelationship(int destinationId, TaxonomyCoordinate tc) {
return getTaxonomyRecordUnpacked().getTypesForRelationship(destinationId, tc);
}
/**
* Gets the write sequence.
*
* @return the write sequence
*/
@Override
public int getWriteSequence() {
return this.writeSequence;
}
//~--- set methods ---------------------------------------------------------
/**
* Sets the write sequence.
*
* @param sequence the new write sequence
*/
@Override
public void setWriteSequence(int sequence) {
this.writeSequence = sequence;
}
}