code: public Collection<String> getHasPluginPrefixes(Map<?, ?> formulaCache) {
  		formula = formula.simplify(formulaCache);
  		if (formula.isTrue()) {
  			return null;
  		}
  		if (formula.isFalse()) {
  			return Collections.emptySet();
  		}
  		Set<String> result = new HashSet<String>();
  		for (BooleanTerm term : formula) {
  			StringBuffer sb = new StringBuffer(pluginName).append("!"); //$NON-NLS-1$
  			for (BooleanVar featureVar : new TreeSet<BooleanVar>(term)) {
  				sb.append(featureVar.name).append("?"); //$NON-NLS-1$
  				if (!featureVar.state) {
  					sb.append(":"); //$NON-NLS-1$
  				}
  			}
  			result.add(sb.toString());
  		}
  		return result;
  	}
docs: A return value of null means that the associated module should be included in the expanded
  dependency list unconditionally. A return value consisting of an empty list means that it
  should not be included at all.
  <p>
  If the list is not empty, then the list elements are the has! plugin prefixes that should be
  used with this module. One module id per list entry specifying the same module name should be
  used.
  <p>
  {@link TreeSet} is used to obtain predictable ordering of terms in compound has conditionals,
  mostly for unit tests.
  
  @param formulaCache
  the formula cache
  
  @return The list of has! plugin prefixes for this module.