Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

104
LINES

< > BotCompany Repo | #1029845 // ConceptsRefChecker - detect + fix broken references

JavaX fragment (include) [tags: use-pretranspiled]

Libraryless. Click here for Pure Java version (16250L/105K).

sclass ConceptsRefChecker {
  Concepts cc;
  new L<Err> errors;
  bool veryVerbose;
  
  sclass Err {}
  srecord ErrNoBackRef(Concept.Ref ref, Concept dest) > Err {}
  srecord ErrSuperfluousBackRef(Concept.Ref ref, Concept dest) > Err {}
  
  srecord ErrDuplicateRef(Concept c) > Err {}
  srecord ErrNullRef(Concept c) > Err {}
  
  srecord ErrMissingRef(Concept c, Concept.Ref ref) > Err {}
  srecord ErrSuperfluousRef(Concept c, Concept.Ref ref) > Err {}
  
  // a reference from a concept that is not in the concepts list
  srecord ErrDanglingSource(Concept.Ref ref, Concept dest) > Err {}
  
  // a reference to a concept that is not in the concepts list
  srecord ErrDanglingDestination(Concept.Ref ref, Concept dest) > Err {}
  
  *() {}
  *(Concepts *cc) {}
  
  L<Err> run() {
    errors.clear();
    if (cc == null) ret errors;
    Cl<Concept> concepts = cc.allConcepts();
    if (veryVerbose)
      print("Checking " + nConcepts(concepts));
    for (Concept c : concepts) try {
      O badElement = firstElementNotSubclassing(c.backRefs, Concept.Ref.class);
      if (badElement != null) continue with print("Bad element in backRefs of " + c + ": " + badElement);
      
      for (Concept.Ref ref : cloneList(c.backRefs)) {
        if (ref! != c)
          errors.add(new ErrSuperfluousBackRef(ref, c));
        if (ref.concept()._concepts != cc)
          errors.add(new ErrDanglingSource(ref, c));
      }
          
      Cl<Concept.Ref> refs = c._refs();
      
      badElement = firstElementNotSubclassing(refs, Concept.Ref.class);
      if (badElement != null) continue with print("Bad element in backRefs of " + c + ": " + badElement);
      
      if (!allUnique(refs))
        errors.add(new ErrDuplicateRef(c));
      if (contains(refs, null))
        errors.add(new ErrNullRef(c));
        
      refs = nonNulls(refs);
      Cl<Concept.Ref> actualRefs = scanConceptForRefs(c);
      for (Concept.Ref ref : listMinusSet(refs, actualRefs))
        errors.add(new ErrSuperfluousRef(c, ref));
      for (Concept.Ref ref : listMinusSet(actualRefs, refs))
        errors.add(new ErrMissingRef(c, ref));
        
      for (Concept.Ref ref : refs)
        if (ref.has()) {
          if (!contains(ref->backRefs, ref))
            errors.add(new ErrNoBackRef(ref, c));
          if (ref->_concepts != cc)
            errors.add(new ErrDanglingDestination(ref, c));
        }
    } catch print e {
      print("Error processing concept " + c);
    }
    ret errors;
  }
  
  L<Err> errors() { ret errors; }
  
  S fixAll() {
    new LS out;
    // start from end because list removes should be faster like this
    for (Err err : reversed(cloneAndClear(errors))) pcall {
      out.add("Processing " + err);
      if (err cast ErrNoBackRef) {
        err.ref.index();
        out.add("  reference added");
      } else if (err cast ErrSuperfluousRef) {
        err.ref.unindexAndDrop();
        out.add("  reference dropped");
      } else if (err cast ErrDanglingSource) {
        err.ref->_removeBackRef(err.ref);
        out.add("  reference removed from destination");
      } else if (err cast ErrDanglingDestination) {
        err.ref->_removeBackRef(err.ref);
        out.add("  reference removed from destination");
      } else if (err cast ErrMissingRef) {
        err.ref.registerRef();
        out.add("  reference registered");
      } else if (err cast ErrSuperfluousBackRef) {
        err.dest._removeBackRef(err.ref);
        out.add("  backreference dropped");
      } else
        out.add("  TODO - fix not implemented");
    }
    ret lines(out);
  }
  
  S runAndFixAll() { run(); ret fixAll(); }
}

download  show line numbers  debug dex  old transpilations   

Travelled to 5 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, tvejysmllsmz, vouqrxazstgt

No comments. add comment

Snippet ID: #1029845
Snippet name: ConceptsRefChecker - detect + fix broken references
Eternal ID of this version: #1029845/29
Text MD5: 3d3c9c60c6febc0bdc33459ea2837e64
Transpilation MD5: 12f401791ec7643c24e390b11eee0691
Author: stefan
Category: javax
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2021-06-27 06:49:30
Source code size: 3735 bytes / 104 lines
Pitched / IR pitched: No / No
Views / Downloads: 320 / 672
Version history: 28 change(s)
Referenced in: #1034167 - Standard Classes + Interfaces (LIVE, continuation of #1003674)