sclass ConceptShadow {
  Map map;
  bool refsConvertedToIDs;
  
  *(Concept c) {
    map = conceptShadow_rawMap(c);
    MetaTransformer tf = metaTransformer_collectionAndMap();
    // dereference concept refs
    map = toSortedArrayBasedMap((Map) tf.transform(lambda1 derefRefOrNull, map);
  }
  
  synchronized selfType convertRefsToIDs() {
    if (refsConvertedToIDs) this;
    set refsConvertedToIDs;
    MetaTransformer tf = metaTransformer_collectionAndMap();
    map = toSortedArrayBasedMap(mapValues(map, o -> tf.transform(lambda1 conceptToIDObj_gen, o)));
    this;
  }
  
  toString { ret "ConceptShadow " + stringIf(refsConvertedToIDs, "[converted] ") + map; }
  
  O get(O key) { ret mapGet(map, key); }
  
  public bool equals(O o) {
    if (o cast ConceptShadow) {
      convertRefsToIDs();
      o.convertRefsToIDs();
      ret eq(map, o.map);
    }
    false;
  }
  
  long id() { ret toLong(get("id")); }
}