1. Project Clover database Sat Feb 2 2019 06:45:20 CET
  2. Package com.xpn.xwiki.internal.merge

File MergeUtils.java

 

Coverage histogram

../../../../../img/srcFileCovDistChart7.png
66% of files have more coverage

Code metrics

16
54
9
1
236
116
23
0.43
6
9
2.56

Classes

Class Line # Actions
MergeUtils 43 54 0% 23 30
0.6202531562%
 

Contributing tests

This file is covered by 27 tests. .

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package com.xpn.xwiki.internal.merge;
21   
22    import java.io.IOException;
23    import java.io.StringReader;
24    import java.util.ArrayList;
25    import java.util.Collections;
26    import java.util.List;
27   
28    import org.apache.commons.io.IOUtils;
29    import org.apache.commons.lang3.ObjectUtils;
30    import org.apache.commons.lang3.StringUtils;
31    import org.xwiki.diff.DiffManager;
32    import org.xwiki.diff.MergeException;
33   
34    import com.xpn.xwiki.doc.merge.MergeResult;
35    import com.xpn.xwiki.web.Utils;
36   
37    /**
38    * Provide some 3 ways merging related methods.
39    *
40    * @version $Id: 055352cc1193701392ddede2a64e579a958066af $
41    * @since 4.1M1
42    */
 
43    public final class MergeUtils
44    {
45    /**
46    * Used to do the actual merge.
47    */
48    private static final DiffManager DIFFMANAGER = Utils.getComponent(DiffManager.class);
49   
50    /**
51    * Utility class.
52    */
 
53  0 toggle private MergeUtils()
54    {
55   
56    }
57   
58    /**
59    * Merge String at lines level.
60    *
61    * @param previousStr previous version of the string
62    * @param newStr new version of the string
63    * @param currentStr current version of the string
64    * @param mergeResult the merge report
65    * @return the merged string or the provided current string if the merge fail
66    */
 
67  97 toggle public static String mergeLines(String previousStr, String newStr, String currentStr, MergeResult mergeResult)
68    {
69  97 org.xwiki.diff.MergeResult<String> result;
70  97 try {
71  97 result = DIFFMANAGER.merge(toLines(previousStr), toLines(newStr), toLines(currentStr), null);
72   
73  97 mergeResult.getLog().addAll(result.getLog());
74   
75  97 String resultStr = fromLines(result.getMerged());
76   
77  97 if (!StringUtils.equals(resultStr, currentStr)) {
78  5 mergeResult.setModified(true);
79    }
80   
81  97 return resultStr;
82    } catch (MergeException e) {
83  0 mergeResult.getLog().error("Failed to execute merge lines", e);
84    }
85   
86  0 return currentStr;
87    }
88   
89    /**
90    * Merge an Object. Use Object#equals to find conflicts.
91    *
92    * @param previousObject previous version of the object
93    * @param newObject new version of the object
94    * @param currentObject current version of the object
95    * @param mergeResult the merge report
96    * @param <T> the type of the objects to merge
97    * @return the merged object or the provided current object if the merge fail
98    */
 
99  407 toggle public static <T> T mergeOject(T previousObject, T newObject, T currentObject, MergeResult mergeResult)
100    {
101  407 if (ObjectUtils.notEqual(previousObject, newObject)) {
102  6 if (ObjectUtils.equals(previousObject, currentObject)) {
103  3 mergeResult.setModified(true);
104  3 return newObject;
105  3 } else if (ObjectUtils.equals(newObject, currentObject)) {
106  1 return currentObject;
107    }
108   
109  2 mergeResult.getLog().error("Failed to merge objects: previous=[{}] new=[{}] current=[{}]", previousObject,
110    newObject, currentObject);
111    }
112   
113  403 return currentObject;
114    }
115   
116    /**
117    * Merge String at characters level.
118    *
119    * @param previousStr previous version of the string
120    * @param newStr new version of the string
121    * @param currentStr current version of the string
122    * @param mergeResult the merge report
123    * @return the merged string or the provided current string if the merge fail
124    */
 
125  0 toggle public static String mergeCharacters(String previousStr, String newStr, String currentStr, MergeResult mergeResult)
126    {
127  0 org.xwiki.diff.MergeResult<Character> result;
128  0 try {
129  0 result = DIFFMANAGER.merge(toCharacters(previousStr), toCharacters(newStr), toCharacters(currentStr), null);
130   
131  0 mergeResult.getLog().addAll(result.getLog());
132   
133  0 String resultStr = fromCharacters(result.getMerged());
134   
135  0 if (!StringUtils.equals(resultStr, currentStr)) {
136  0 mergeResult.setModified(true);
137    }
138   
139  0 return resultStr;
140    } catch (MergeException e) {
141  0 mergeResult.getLog().error("Failed to execute merge characters", e);
142    }
143   
144  0 return currentStr;
145    }
146   
147    /**
148    * Merge a {@link List}.
149    *
150    * @param <T> the type of the lists elements
151    * @param commonAncestor previous version of the collection
152    * @param next new version of the collection
153    * @param current current version of the collection to modify
154    * @param mergeResult the merge report
155    */
 
156  3 toggle public static <T> void mergeList(List<T> commonAncestor, List<T> next, List<T> current, MergeResult mergeResult)
157    {
158  3 org.xwiki.diff.MergeResult<T> result;
159  3 try {
160  3 result = DIFFMANAGER.merge(commonAncestor, next, current, null);
161   
162  3 mergeResult.getLog().addAll(result.getLog());
163   
164  3 List<T> merged = result.getMerged();
165   
166  3 if (!ObjectUtils.equals(merged, current)) {
167  1 current.clear();
168  1 current.addAll(result.getMerged());
169  1 mergeResult.setModified(true);
170    }
171    } catch (MergeException e) {
172  0 mergeResult.getLog().error("Failed to execute merge lists", e);
173    }
174    }
175   
176    /**
177    * @param lines the lines
178    * @return the multilines text
179    */
 
180  97 toggle private static String fromLines(List<String> lines)
181    {
182  97 return StringUtils.join(lines, '\n');
183    }
184   
185    /**
186    * @param str the multilines text
187    * @return the lines
188    */
 
189  291 toggle private static List<String> toLines(String str)
190    {
191  291 List<String> result;
192  291 try {
193  291 result = IOUtils.readLines(new StringReader(str));
194   
195    // Handle special case where the string ends with a new line
196  291 if (str.endsWith("\n") || str.endsWith("\r") || str.endsWith("\r\n")) {
197  4 result.add("");
198    }
199   
200    } catch (IOException e) {
201    // Should never happen
202  0 result = null;
203    }
204  291 return result;
205    }
206   
207    /**
208    * @param characters the characters
209    * @return the single line text
210    */
 
211  0 toggle private static String fromCharacters(List<Character> characters)
212    {
213  0 return StringUtils.join(characters, null);
214    }
215   
216    /**
217    * @param str the single line text
218    * @return the lines
219    */
 
220  0 toggle private static List<Character> toCharacters(String str)
221    {
222  0 List<Character> characters;
223   
224  0 if (str != null) {
225  0 characters = new ArrayList<Character>(str.length());
226   
227  0 for (char c : str.toCharArray()) {
228  0 characters.add(c);
229    }
230    } else {
231  0 characters = Collections.emptyList();
232    }
233   
234  0 return characters;
235    }
236    }