protected void add(ST tag) throws SharkKBException {
    // only add if not yet in storage
    ST st = this.getSemanticTag(tag.getSI());

    if (st != null) return; // do nothing

    if (tag instanceof InMemoSemanticTag) {
      ((InMemoSemanticTag) tag).setStorage(this);
    }

    this.put(tag);
  }
  protected void removeSemanticTag(ST tag) {
    this.tags.remove(tag);

    // tag is removed - remove reference in si2tag list

    String[] sis = tag.getSI();
    if (sis == null | sis.length == 0) {
      return;
    }

    for (int i = 0; i < sis.length; i++) {
      this.si2tag.remove(sis[i]);
    }
  }
  protected final void put(ST tag) {
    this.tags.add(tag);

    // recreate si list - not a very performant implementation have to confess...
    //        this.initSi();

    String[] sis = tag.getSI();
    if (sis == null) {
      return;
    }

    for (int i = 0; i < sis.length; i++) {
      this.si2tag.put(sis[i], tag);
    }
  }
  ST merge(ST source) throws SharkKBException {
    SemanticTag copyTag = null;

    if (source == null) {
      return null;
    }

    // try to find tag
    copyTag = this.getSemanticTag(source.getSI());

    if (copyTag == null) {

      if (source instanceof PeerTXSemanticTag) {
        copyTag = InMemoSharkKB.createInMemoCopy((PeerTXSemanticTag) source);
      } else if (source instanceof PeerSNSemanticTag) {
        copyTag = InMemoSharkKB.createInMemoCopy((PeerTXSemanticTag) source);
      } else if (source instanceof TimeSemanticTag) {
        copyTag = InMemoSharkKB.createInMemoCopy((TimeSemanticTag) source);
      } else if (source instanceof SpatialSemanticTag) {
        copyTag = InMemoSharkKB.createInMemoCopy((SpatialSemanticTag) source);
      } else if (source instanceof TXSemanticTag) {
        copyTag = InMemoSharkKB.createInMemoCopy((TXSemanticTag) source);
      } else if (source instanceof PeerSemanticTag) {
        copyTag = InMemoSharkKB.createInMemoCopy((PeerSemanticTag) source);
      } else if (source instanceof SNSemanticTag) {
        copyTag = InMemoSharkKB.createInMemoCopy((SNSemanticTag) source);
      } else if (source instanceof SemanticTag) {
        copyTag = InMemoSharkKB.createInMemoCopy((SemanticTag) source);
      }

      this.add((ST) copyTag);
    } else {
      SharkCSAlgebra.merge(copyTag, source);
    }

    //        this.initSi();

    return (ST) copyTag;
  }