/**
  * Offers an alternative to the default <code>toString()</code> method. Uses <code>env</code> to
  * determine the containing model of types. Compensates for {@link EObject}'s notoriously bad
  * <code>toString()</code>.
  *
  * @param object
  * @param env
  * @return the string representation of <code>object</code>.
  * @see EMFTVMUtil#toPrettyString(Object, ExecEnv)
  */
 public String toPrettyString(final ETypedElement element, final ExecEnv env) {
   final StringBuilder sb = new StringBuilder();
   sb.append(EMFTVMUtil.toPrettyString(element.getEType(), env));
   if (element.getUpperBound() != 1) {
     sb.append(" [").append(element.getLowerBound()).append("..");
     if (element.getUpperBound() == -1) {
       sb.append('*');
     } else {
       sb.append(element.getUpperBound());
     }
     sb.append(']');
   }
   return sb.toString();
 }
 /**
  * Returns the {@link EStructuralFeature} and {@link EOperation} syntax completion proposals for
  * the given prefix and root.
  *
  * @param prefix the syntax prefix
  * @param root the root AST node
  * @param propertyCallType the {@link PropertyCallType}
  * @return the syntax completion proposals
  */
 protected List<SyntaxCompletionProposal> getEFeatureProposals(
     final String prefix, final EObject root, final PropertyCallType propertyCallType) {
   if (propertyCallType != PropertyCallType.REGULAR
       || !(root instanceof org.eclipselabs.simpleocl.Module)) {
     return Collections.<SyntaxCompletionProposal>emptyList();
   }
   final String strippedPrefix = stripPropertyCallPrefix(prefix);
   final SortedSet<String> features = new TreeSet<String>();
   final Map<String, URL> images = new HashMap<String, URL>();
   final Map<String, String> displayStrings = new HashMap<String, String>();
   final org.eclipselabs.simpleocl.Module module = (org.eclipselabs.simpleocl.Module) root;
   final ExecEnv env = EmftvmFactory.eINSTANCE.createExecEnv();
   loadMetamodels(module, env);
   for (OclMetamodel metamodel : module.getMetamodels()) {
     try {
       final URI emfURI = URI.createURI(metamodel.getUri());
       final ResourceSet rs = new ResourceSetImpl();
       final Resource resource = rs.getResource(emfURI, true);
       for (EObject eObject : new ResourceIterable(resource)) {
         if (!(eObject.eContainer() instanceof EClassifier)) {
           continue;
         }
         if (eObject instanceof EStructuralFeature || eObject instanceof EOperation) {
           String name = ((ETypedElement) eObject).getName();
           if (strippedPrefix.isEmpty() || name.startsWith(strippedPrefix)) {
             StringBuilder sb = new StringBuilder(name);
             StringBuilder displayString = new StringBuilder(name);
             if (eObject instanceof EOperation) {
               sb.append('(');
               displayString.append('(');
               boolean first = true;
               for (EParameter par : ((EOperation) eObject).getEParameters()) {
                 if (!first) {
                   sb.append(", ");
                   displayString.append(", ");
                 }
                 sb.append(par.getName());
                 displayString
                     .append(par.getName())
                     .append(" : ")
                     .append(toPrettyString(par, env));
                 first = false;
               }
               sb.append(')');
               displayString.append(')');
             }
             displayString
                 .append(" : ")
                 .append(toPrettyString((ETypedElement) eObject, env))
                 .append(" - ")
                 .append(EMFTVMUtil.toPrettyString(eObject.eContainer(), env));
             features.add(sb.toString());
             ItemProviderAdapter itemProviderAdapter =
                 (ItemProviderAdapter) ecoreItemProviderFactory.createAdapter(eObject);
             images.put(
                 sb.toString(), getItemProviderImageURL(itemProviderAdapter.getImage(eObject)));
             displayStrings.put(sb.toString(), displayString.toString());
           }
         }
       }
     } catch (RuntimeException e) {
       SimpleoclUIPlugin.logError(e.getLocalizedMessage(), e);
     }
   }
   return buildProposals(prefix, root, features, images, displayStrings);
 }