private Item intern(Item item) {
   if (item.sameSymbol(ANY.getSymbol())) return ANY;
   if (item.sameSymbol(VAR.getSymbol())) return VAR;
   if (item.sameSymbol(TERM.getSymbol())) return TERM;
   if (item.sameSymbol(URI.getSymbol())) return URI;
   if (item.sameSymbol(LITERAL.getSymbol())) return LITERAL;
   if (item.sameSymbol(BNODE.getSymbol())) return BNODE;
   return item;
 }
 @Override
 public Formula apply(final Formula formula, boolean cache) {
   if (!this.proceed) return null;
   if (formula.type().precedence() >= LITERAL.precedence()) return formula;
   Formula cached = formula.transformationCacheEntry(FACTORIZED_CNF);
   if (cached != null) return cached;
   switch (formula.type()) {
     case NOT:
     case IMPL:
     case EQUIV:
       cached = this.apply(formula.nnf(), cache);
       break;
     case OR:
       LinkedHashSet<Formula> nops = new LinkedHashSet<>();
       for (final Formula op : formula) {
         if (!this.proceed) return null;
         nops.add(this.apply(op, cache));
       }
       final Iterator<Formula> it = nops.iterator();
       cached = it.next();
       while (it.hasNext()) {
         if (!this.proceed) return null;
         cached = this.distribute(cached, it.next());
       }
       break;
     case AND:
       nops = new LinkedHashSet<>();
       for (final Formula op : formula) {
         final Formula apply = this.apply(op, cache);
         if (!this.proceed) return null;
         nops.add(apply);
       }
       cached = formula.factory().and(nops);
       break;
     case PBC:
       cached = formula.nnf();
       break;
     default:
       throw new IllegalArgumentException("Could not process the formula type " + formula.type());
   }
   if (this.proceed) {
     if (cache) formula.setTransformationCacheEntry(FACTORIZED_CNF, cached);
     return cached;
   }
   return null;
 }