--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.corext.refactoring.nls;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+
+import com.ibm.icu.text.Collator;
+
+import org.eclipse.text.edits.DeleteEdit;
+import org.eclipse.text.edits.InsertEdit;
+import org.eclipse.text.edits.ReplaceEdit;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.TextUtilities;
+
+import org.eclipse.ltk.core.refactoring.TextChange;
+
+import org.eclipse.jdt.internal.ui.propertiesfileeditor.PropertiesFileEscapes;
+
+public class PropertyFileDocumentModel {
+
+ List<KeyValuePairModell> fKeyValuePairs;
+ private String fLineDelimiter;
+
+ public PropertyFileDocumentModel(IDocument document) {
+ parsePropertyDocument(document);
+ fLineDelimiter= TextUtilities.getDefaultLineDelimiter(document);
+ }
+
+ /**
+ * @return the line delimiter used by the document described by this model
+ */
+ public String getLineDelimiter() {
+ return fLineDelimiter;
+ }
+
+ /**
+ * Return the key value pair in this model with the key <code>key</code>
+ *
+ * @param key the key of the pair
+ * @return the pair with the key or <b>null</b> if no such pair.
+ */
+ public KeyValuePair getKeyValuePair(String key) {
+ for (int i= 0; i < fKeyValuePairs.size(); i++) {
+ KeyValuePairModell keyValuePair = fKeyValuePairs.get(i);
+ if (keyValuePair.getKey().equals(key)) {
+ return keyValuePair;
+ }
+ }
+ return null;
+ }
+
+ InsertEdit insert(KeyValuePair keyValuePair) {
+ KeyValuePairModell keyValuePairModell = new KeyValuePairModell(keyValuePair);
+ int index = findInsertPosition(keyValuePairModell);
+ KeyValuePairModell insertHere = fKeyValuePairs.get(index);
+ int offset = insertHere.fOffset;
+
+ String extra= ""; //$NON-NLS-1$
+ if (insertHere instanceof LastKeyValuePair && ((LastKeyValuePair)insertHere).needsNewLine()) {
+ extra= fLineDelimiter;
+ ((LastKeyValuePair)insertHere).resetNeedsNewLine();
+ offset-= insertHere.fLeadingWhiteSpaces;
+ } else if (index > 0) {
+ String beforeKey= fKeyValuePairs.get(index - 1).fKey;
+ String afterKey= insertHere.fKey;
+ String key= keyValuePair.fKey;
+ int distBefore= NLSUtil.invertDistance(key, beforeKey);
+ int distAfter= NLSUtil.invertDistance(key, afterKey);
+ if (distBefore > distAfter) {
+ offset-= insertHere.fLeadingWhiteSpaces;
+ } else if (distBefore == distAfter && Collator.getInstance().compare(beforeKey, afterKey) < 0) {
+ offset-= insertHere.fLeadingWhiteSpaces;
+ } else {
+ //insert it before afterKey -> move the leading white spaces to the inserted pair
+ keyValuePairModell.fLeadingWhiteSpaces= insertHere.fLeadingWhiteSpaces;
+ insertHere.fLeadingWhiteSpaces= 0;
+ }
+ }
+
+ String text= keyValuePairModell.generated_875148158285524824(this, index, offset, extra);
+ return new InsertEdit(offset, text);
+ }
+
+ /**
+ * Inserts the given key value pairs into this model at appropriate
+ * positions. Records all required text changes in the given change
+ *
+ * @param keyValuePairs the key value pairs to insert
+ * @param change the change to use to record text changes
+ */
+ public void insert(KeyValuePair[] keyValuePairs, TextChange change) {
+
+ ArrayList<KeyValuePair> sorted= new ArrayList<KeyValuePair>(Arrays.asList(keyValuePairs));
+ Collections.sort(sorted, new Comparator<KeyValuePair>() {
+ public int compare(KeyValuePair p1, KeyValuePair p2) {
+ return Collator.getInstance().compare(p1.fKey, p2.fKey);
+ }
+ });
+
+ for (int i = 0; i < sorted.size(); i++) {
+ KeyValuePair curr= sorted.get(i);
+ curr.generated_45942992453355874(change, this);
+ }
+ }
+
+ public DeleteEdit remove(String key) {
+ for (Iterator<KeyValuePairModell> iter = fKeyValuePairs.iterator(); iter.hasNext();) {
+ KeyValuePairModell keyValuePair = iter.next();
+ if (keyValuePair.fKey.equals(key)) {
+ return keyValuePair.generated_6789650072710353462(this);
+ }
+ }
+ return null;
+ }
+
+ public ReplaceEdit replace(KeyValuePair toReplace, KeyValuePair replaceWith) {
+ for (Iterator<KeyValuePairModell> iter = fKeyValuePairs.iterator(); iter.hasNext();) {
+ KeyValuePairModell keyValuePair = iter.next();
+ if (keyValuePair.fKey.equals(toReplace.getKey())) {
+ String newText= new KeyValuePairModell(replaceWith).getKeyValueText();
+ return keyValuePair.generated_6698145679089660767(this, newText);
+ }
+ }
+ return null;
+ }
+
+ private int findInsertPosition(KeyValuePairModell keyValuePair) {
+ ArrayList<String> keys= new ArrayList<String>();
+ for (int i= 0; i < fKeyValuePairs.size(); i++) {
+ KeyValuePairModell element = fKeyValuePairs.get(i);
+ element.generated_326054000021849204(keys);
+ }
+ int insertIndex= NLSUtil.getInsertionPosition(keyValuePair.getKey(), keys);
+
+ if (insertIndex < fKeyValuePairs.size() - 1) {
+ insertIndex++;
+ }
+
+ return insertIndex;
+ }
+
+ private void parsePropertyDocument(IDocument document) {
+ fKeyValuePairs = new ArrayList<KeyValuePairModell>();
+
+ SimpleLineReader reader = new SimpleLineReader(document);
+ int offset = 0;
+ LastKeyValuePair lastKeyValuePair= reader.generated_689189764367573075(document, this, offset);
+ fKeyValuePairs.add(lastKeyValuePair);
+ }
+
+ int getIndexOfSeparationCharacter(String line) {
+ int minIndex = -1;
+ int indexOfEven = line.indexOf('=');
+ int indexOfColumn = line.indexOf(':');
+ int indexOfBlank = line.indexOf(' ');
+
+ if ((indexOfEven != -1) && (indexOfColumn != -1)) {
+ minIndex = Math.min(indexOfEven, indexOfColumn);
+ } else {
+ minIndex = Math.max(indexOfEven, indexOfColumn);
+ }
+
+ if ((minIndex == -1) && (indexOfBlank != -1)) {
+ minIndex= indexOfBlank;
+ }
+
+ return minIndex;
+ }
+
+ public static String escape(String s, boolean escapeCommentCharsAndLeadingWhitespaces) {
+ StringBuffer sb= new StringBuffer(s.length());
+ int length= s.length();
+ for (int i= 0; i < length; i++){
+ char c= s.charAt(i);
+ sb.append(PropertiesFileEscapes.escape(c));
+ }
+ if(!escapeCommentCharsAndLeadingWhitespaces)
+ return sb.toString();
+ return escapeLeadingWhiteSpaces(escapeCommentChars(sb.toString()));
+ }
+
+ private static String escapeCommentChars(String string) {
+ StringBuffer sb = new StringBuffer(string.length() + 5);
+ for (int i = 0; i < string.length(); i++) {
+ char c = string.charAt(i);
+ switch (c) {
+ case '!':
+ sb.append("\\!"); //$NON-NLS-1$
+ break;
+ case '#':
+ sb.append("\\#"); //$NON-NLS-1$
+ break;
+ default:
+ sb.append(c);
+ }
+ }
+ return sb.toString();
+ }
+
+ private static String escapeLeadingWhiteSpaces(String str) {
+ int firstNonWhiteSpace= findFirstNonWhiteSpace(str);
+ StringBuffer buf= new StringBuffer(firstNonWhiteSpace);
+ for (int i = 0; i < firstNonWhiteSpace; i++) {
+ buf.append('\\');
+ buf.append(str.charAt(i));
+ }
+ buf.append(str.substring(firstNonWhiteSpace));
+ return buf.toString();
+ }
+
+ /**
+ * @param s the string to inspect
+ * @return the first non whitespace character, the length if only whitespace characters
+ */
+ private static int findFirstNonWhiteSpace(String s) {
+ for (int i = 0; i < s.length(); i++) {
+ if (!Character.isWhitespace(s.charAt(i)))
+ return i;
+ }
+ return s.length();
+ }
+
+ static class KeyValuePairModell extends KeyValuePair {
+
+ int fOffset;
+ int fLength;
+ int fLeadingWhiteSpaces;
+
+ public KeyValuePairModell(String key, String value, int offset, int length, int leadingWhiteSpaces) {
+ super(key, value);
+ fOffset = offset;
+ fLength = length;
+ fLeadingWhiteSpaces = leadingWhiteSpaces;
+ }
+
+ public KeyValuePairModell(KeyValuePair keyValuePair) {
+ super(keyValuePair.fKey, keyValuePair.fValue);
+ }
+
+ public int getLength() {
+ return fLength;
+ }
+
+ String getKeyValueText() {
+ return fKey + '=' + fValue;
+ }
+
+ public String generated_875148158285524824(PropertyFileDocumentModel propertyfiledocumentmodel, int index, int offset, String extra) {
+ String text= extra + getKeyValueText();
+ fOffset= offset;
+ fLength= text.length();
+ propertyfiledocumentmodel.fKeyValuePairs.add(index, this);
+ return text;
+ }
+
+ public DeleteEdit generated_6789650072710353462(PropertyFileDocumentModel propertyfiledocumentmodel) {
+ return new DeleteEdit(fOffset, getLength());
+ }
+
+ public ReplaceEdit generated_6698145679089660767(PropertyFileDocumentModel propertyfiledocumentmodel, String newText) {
+ return new ReplaceEdit(fOffset, getLength(), newText);
+ }
+
+ public void generated_326054000021849204(ArrayList<String> keys) {
+ if (! (this instanceof LastKeyValuePair))
+ keys.add(getKey());
+ }
+ }
+
+ /**
+ * anchor element for a list of KeyValuePairs. (it is greater than every
+ * other KeyValuePair)
+ */
+ static class LastKeyValuePair extends KeyValuePairModell {
+
+ private boolean fNeedsNewLine;
+
+ public LastKeyValuePair(int offset, boolean needsNewLine) {
+ super("zzzzzzz", "key", offset, 7 + 1 + 3, 0); //$NON-NLS-1$ //$NON-NLS-2$
+ fNeedsNewLine= needsNewLine;
+ }
+ public boolean needsNewLine() {
+ return fNeedsNewLine;
+ }
+ public void resetNeedsNewLine() {
+ fNeedsNewLine= false;
+ }
+ }
+}