private List<SNode> getNodesImpl(String conceptFQName, boolean includeInherited) {
   if (includeInherited) {
     Set<String> allDescendantsOfConcept =
         ConceptDescendantsCache.getInstance().getDescendants(conceptFQName);
     final ArrayList<List<SNode>> nodesOfConcept =
         new ArrayList<List<SNode>>(allDescendantsOfConcept.size());
     int cnt = 0;
     synchronized (myNodeMap) { // utilize the fact values in map are immutable
       for (String d : allDescendantsOfConcept) {
         List<SNode> n = myNodeMap.get(d);
         nodesOfConcept.add(n);
         cnt += n.size();
       }
     }
     final ArrayList<SNode> result = new ArrayList<SNode>(cnt);
     for (List<SNode> l : nodesOfConcept) {
       result.addAll(l);
     }
     return result;
   } else {
     synchronized (myNodeMap) {
       return myNodeMap.get(conceptFQName);
     }
   }
 }
 /** Subclasses shall invoke once model had changed */
 protected void removed(SNode n) {
   if (myNodeMap.isEmpty()) {
     return;
   }
   ConceptInstanceMap toDelete = build(new ConceptNodeMapBuilder(n));
   synchronized (myNodeMap) {
     myNodeMap.forget(toDelete);
   }
 }
 /** Subclasses shall invoke once model had changed */
 protected void added(SNode n) {
   if (myNodeMap.isEmpty()) {
     return;
   }
   ConceptInstanceMap toAdd = build(new ConceptNodeMapBuilder(n));
   synchronized (myNodeMap) {
     myNodeMap.merge(toAdd);
   }
 }
  @Override
  public List<SNode> getNodes(String conceptFqName, boolean includeInherited) {
    // notify 'model nodes read access'
    myModel.getRootNodes().iterator();

    if (!myNodeMap.isEmpty()) {
      return getNodesImpl(conceptFqName, includeInherited);
    }
    synchronized (myNodeMap) {
      if (myNodeMap.isEmpty()) {
        ConceptInstanceMap all = build(new ConceptNodeMapBuilder(myModel));
        all.trimValues(); // merge may reuse lists,
        myNodeMap.merge(all);
      }
      return getNodesImpl(conceptFqName, includeInherited);
    }
  }
 /** Subclasses shall invoke once model had changed */
 protected void reset() {
   synchronized (myNodeMap) {
     myNodeMap.clear();
   }
 }