docs: public int countAndLogWarnings() {
          final List<String> warnings = new LinkedList<>();
  
          // find elements with a missing description
          getModel().getElements().stream()
                  .filter(e -> !(e instanceof ContainerInstance) && !(e instanceof DeploymentNode))
                  .filter(e -> e.getDescription() == null || e.getDescription().trim().length() == 0)
                  .forEach(e -> warnings.add("The " + typeof(e) + " \"" + e.getCanonicalName().substring(1) + "\" is missing a description."));
  
          // find containers with a missing technology
          getModel().getElements().stream()
                  .filter(e -> e instanceof Container)
                  .map(e -> (Container)e)
                  .filter(c -> c.getTechnology() == null || c.getTechnology().trim().length() == 0)
                  .forEach(c -> warnings.add("The container \"" + c.getCanonicalName().substring(1) + "\" is missing a technology."));
  
          // find components with a missing technology
          getModel().getElements().stream()
                  .filter(e -> e instanceof Component)
                  .map(e -> (Component)e)
                  .filter(c -> c.getTechnology() == null || c.getTechnology().trim().length() == 0)
                  .forEach(c -> warnings.add("The component \"" + c.getCanonicalName().substring(1) + "\" is missing a technology."));
  
          // find component relationships with a missing description
          for (Relationship relationship : getModel().getRelationships()) {
              if (relationship.getSource() instanceof Component && relationship.getDestination() instanceof Component &&
                      relationship.getSource().getParent().equals(relationship.getDestination().getParent())) {
                  // ignore component-component relationships inside the same container because these are
                  // often identified using reflection and won't have a description
                  // (i.e. let's not flood the user with warnings)
              } else {
                  if (relationship.getDescription() == null || relationship.getDescription().trim().length() == 0) {
                      warnings.add("The relationship between " + typeof(relationship.getSource()) + " \"" + relationship.getSource().getCanonicalName().substring(1) + "\" and " + typeof(relationship.getDestination()) + " \"" + relationship.getDestination().getCanonicalName().substring(1) + "\" is missing a description.");
                  }
              }
          }
  
          // diagram keys have not been specified - this is only applicable to
          // workspaces created with the early versions of Structurizr for Java
          getViews().getSystemLandscapeViews().stream()
                  .filter(v -> v.getKey() == null)
                  .forEach(v -> warnings.add("System Landscape view \"" + v.getName() + "\": Missing key"));
          getViews().getSystemContextViews().stream()
                  .filter(v -> v.getKey() == null)
                  .forEach(v -> warnings.add("System Context view \"" + v.getName() + "\": Missing key"));
          getViews().getContainerViews().stream()
                  .filter(v -> v.getKey() == null)
                  .forEach(v -> warnings.add("Container view \"" + v.getName() + "\": Missing key"));
          getViews().getComponentViews().stream()
                  .filter(v -> v.getKey() == null)
                  .forEach(v -> warnings.add("Component view \"" + v.getName() + "\": Missing key"));
          getViews().getDynamicViews().stream()
                  .filter(v -> v.getKey() == null)
                  .forEach(v -> warnings.add("Dynamic view \"" + v.getName() + "\": Missing key"));
          getViews().getDeploymentViews().stream()
                  .filter(v -> v.getKey() == null)
                  .forEach(v -> warnings.add("Deployment view \"" + v.getName() + "\": Missing key"));
  
          warnings.forEach(log::warn);
  
          return warnings.size();
      }