public SpringPropertiesReconciler createReconciler(
     ISourceViewer sourceViewer,
     DocumentContextFinder documentContextFinder,
     IReconcileTrigger reconcileTigger) {
   IReconcilingStrategy strategy = null;
   if (!DISABLE_SPELL_CHECKER
       && EditorsUI.getPreferenceStore().getBoolean(SpellingService.PREFERENCE_SPELLING_ENABLED)) {
     IReconcilingStrategy spellcheck =
         new SpellingReconcileStrategy(sourceViewer, EditorsUI.getSpellingService()) {
           @Override
           protected IContentType getContentType() {
             return SpringPropertiesFileEditor.CONTENT_TYPE;
           }
         };
     strategy = ReconcilingUtil.compose(strategy, spellcheck);
   }
   try {
     IReconcileEngine reconcileEngine = createEngine();
     IReconcilingStrategy propertyChecker =
         new SpringPropertiesReconcileStrategy(
             sourceViewer, reconcileEngine, documentContextFinder, reconcileTigger);
     strategy = ReconcilingUtil.compose(strategy, propertyChecker);
   } catch (Exception e) {
     SpringPropertiesEditorPlugin.log(e);
   }
   if (strategy != null) {
     SpringPropertiesReconciler reconciler = new SpringPropertiesReconciler(strategy);
     reconciler.setDelay(500);
     return reconciler;
   }
   return null;
 }
 public IRegion getHoverRegion(IDocument document, int offset) {
   try {
     ITypedRegion candidate = getPartition(document, offset);
     if (candidate != null && candidate.getType() == IDocument.DEFAULT_CONTENT_TYPE) {
       return candidate;
     }
   } catch (Exception e) {
     SpringPropertiesEditorPlugin.log(e);
   }
   return null;
 }
 public static int skipWhiteSpace(IDocument doc, int pos) {
   try {
     int end = doc.getLength();
     while (pos < end && Character.isWhitespace(doc.getChar(pos))) {
       pos++;
     }
     if (pos < end) {
       return pos;
     }
   } catch (Exception e) {
     SpringPropertiesEditorPlugin.log(e);
   }
   return -1;
 }
 private int findValueStart(IDocument doc, int pos) {
   try {
     pos = skipWhiteSpace(doc, pos);
     if (pos >= 0) {
       char assign = doc.getChar(pos);
       if (!isAssign(assign)) {
         return pos; // For the case where key and value are separated by whitespace instead of
                     // assignment
       }
       pos = skipWhiteSpace(doc, pos + 1);
       if (pos >= 0) {
         return pos;
       }
     }
   } catch (Exception e) {
     SpringPropertiesEditorPlugin.log(e);
   }
   return -1;
 }
 private Collection<ICompletionProposal> getValueCompletions(
     IDocument doc, int offset, ITypedRegion valuePartition) {
   int regionStart = valuePartition.getOffset();
   int startOfValue = findValueStart(doc, regionStart);
   try {
     String valuePrefix;
     if (startOfValue >= 0 && startOfValue < offset) {
       valuePrefix = doc.get(startOfValue, offset - startOfValue);
     } else {
       startOfValue = offset;
       valuePrefix = "";
     }
     EnumCaseMode caseMode = caseMode(valuePrefix);
     String propertyName =
         fuzzySearchPrefix.getPrefix(
             doc, regionStart); // note: no need to skip whitespace backwards.
     // because value partition includes whitespace around the assignment
     if (propertyName != null) {
       Type type = getValueType(propertyName);
       String[] valueCompletions = typeUtil.getAllowedValues(type, caseMode);
       if (valueCompletions != null && valueCompletions.length > 0) {
         ArrayList<ICompletionProposal> proposals = new ArrayList<ICompletionProposal>();
         for (int i = 0; i < valueCompletions.length; i++) {
           String valueCandidate = valueCompletions[i];
           double score = FuzzyMatcher.matchScore(valuePrefix, valueCandidate);
           if (score != 0) {
             DocumentEdits edits = new DocumentEdits(doc);
             edits.delete(startOfValue, offset);
             edits.insert(offset, valueCandidate);
             proposals.add(
                 completionFactory.valueProposal(valueCandidate, type, score, edits)
                 // new ValueProposal(startOfValue, valuePrefix, valueCandidate, i)
                 );
           }
         }
         return proposals;
       }
     }
   } catch (Exception e) {
     SpringPropertiesEditorPlugin.log(e);
   }
   return Collections.emptyList();
 }
 public SpringPropertyHoverInfo getHoverInfo(IDocument doc, IRegion region) {
   debug("getHoverInfo(" + region + ")");
   // The delegate 'getHoverRegion' for spring propery editor will return smaller word regions.
   // we must ensure to use our own region finder to identify correct property name.
   region = getHoverRegion(doc, region.getOffset());
   if (region != null) {
     try {
       //			if (contentType.equals(IDocument.DEFAULT_CONTENT_TYPE)) {
       debug("hoverRegion = " + region);
       PropertyInfo best =
           findBestHoverMatch(doc.get(region.getOffset(), region.getLength()).trim());
       if (best != null) {
         return new SpringPropertyHoverInfo(documentContextFinder.getJavaProject(doc), best);
       }
       //			}
     } catch (Exception e) {
       SpringPropertiesEditorPlugin.log(e);
     }
   }
   return null;
 }
 /*
  * @see org.eclipse.jface.action.Action#run()
  */
 @Override
 public void run() {
   try {
     BrowserInformationControlInput input = fInfoControl.getInput();
     if (input instanceof HoverInfo) {
       HoverInfo infoInput = (HoverInfo) input;
       if (infoInput != null) {
         List<IJavaElement> elements = infoInput.getJavaElements();
         // TODO: This only opens the first element, if there's more than one should offer a
         // choice/
         if (!elements.isEmpty()) {
           IJavaElement je = elements.get(0);
           fInfoControl.notifyDelayedInputChange(null);
           fInfoControl.dispose(); // FIXME: should have protocol to hide, rather than dispose
           JavaUI.openInEditor(je);
         }
       }
     }
   } catch (Exception e) {
     SpringPropertiesEditorPlugin.log(e);
   }
 }