001: /**
002: * LibreSource
003: * Copyright (C) 2004-2008 Artenum SARL / INRIA
004: * http://www.libresource.org - contact@artenum.com
005: *
006: * This file is part of the LibreSource software,
007: * which can be used and distributed under license conditions.
008: * The license conditions are provided in the LICENSE.TXT file
009: * at the root path of the packaging that enclose this file.
010: * More information can be found at
011: * - http://dev.libresource.org/home/license
012: *
013: * Initial authors :
014: *
015: * Guillaume Bort / INRIA
016: * Francois Charoy / Universite Nancy 2
017: * Julien Forest / Artenum
018: * Claude Godart / Universite Henry Poincare
019: * Florent Jouille / INRIA
020: * Sebastien Jourdain / INRIA / Artenum
021: * Yves Lerumeur / Artenum
022: * Pascal Molli / Universite Henry Poincare
023: * Gerald Oster / INRIA
024: * Mariarosa Penzi / Artenum
025: * Gerard Sookahet / Artenum
026: * Raphael Tani / INRIA
027: *
028: * Contributors :
029: *
030: * Stephane Bagnier / Artenum
031: * Amadou Dia / Artenum-IUP Blois
032: * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
033: */package org.libresource.so6.core.tf;
034:
035: import org.libresource.so6.core.WsConnection;
036: import org.libresource.so6.core.command.Command;
037: import org.libresource.so6.core.command.Id;
038: import org.libresource.so6.core.command.Macro;
039: import org.libresource.so6.core.command.NoOp;
040: import org.libresource.so6.core.command.text.AddBlock;
041: import org.libresource.so6.core.command.text.DelBlock;
042: import org.libresource.so6.core.command.text.UpdateTextFile;
043: import org.libresource.so6.core.engine.util.ObjectCloner;
044:
045: import java.lang.reflect.Method;
046:
047: import java.util.ArrayList;
048: import java.util.Iterator;
049:
050: /**
051: * @author Ecoo Team Loria
052: */
053: public class TextFileFunctions {
054: public final static String CONFLICT_BLOC_START = ">>>> CONFLICT >>>> ";
055: public final static String CONFLICT_BLOC_END = "<<<< CONFLICT <<<<";
056: public final static String CONFLICT_BLOC_SPLIT = "==== ";
057: public final static String CONFLICT_BLOC_PADDING = ">";
058: public final static String CONFLICT_BLOC_ORIGINE_SEPARATOR = " / ";
059: public final static String CONFLICT_TYPE_ADD_ADD = "ADD - ADD";
060: public final static String CONFLICT_TYPE_ADD_REMOVE = "ADD - REMOVE";
061: public final static String CONFLICT_TYPE_REMOVE_ADD = "REMOVE - ADD";
062: public final static int ADD_ADD = 1;
063: public final static int ADD_REMOVE = 2;
064: public final static int REMOVE_ADD = 3;
065: private WsConnection ws;
066:
067: public TextFileFunctions(WsConnection ws) {
068: this .ws = ws;
069: }
070:
071: public static String[] getOrigineBlocNames(String splitLine) {
072: return splitLine.substring(CONFLICT_BLOC_SPLIT.length()).split(
073: CONFLICT_BLOC_ORIGINE_SEPARATOR);
074: }
075:
076: public static int getConflictType(String firstConflictLine) {
077: if (firstConflictLine.endsWith(CONFLICT_TYPE_ADD_ADD)) {
078: return ADD_ADD;
079: }
080:
081: if (firstConflictLine.endsWith(CONFLICT_TYPE_ADD_REMOVE)) {
082: return ADD_REMOVE;
083: }
084:
085: if (firstConflictLine.endsWith(CONFLICT_TYPE_REMOVE_ADD)) {
086: return REMOVE_ADD;
087: }
088:
089: return -1;
090: }
091:
092: public Command transp(UpdateTextFile c1, UpdateTextFile c2)
093: throws Exception {
094: Command res = null;
095: Method m = null;
096:
097: try {
098: // Make transformation only if needed
099: if (c1.getPath().equals(c2.getPath())) {
100: m = this .getClass().getMethod("tf",
101: new Class[] { c1.getClass(), c2.getClass() });
102: } else {
103: return c1;
104: }
105: } catch (NoSuchMethodException e1) {
106: try {
107: m = this .getClass().getMethod(
108: "tf",
109: new Class[] { c1.getClass().getSuperclass(),
110: c2.getClass() });
111: } catch (NoSuchMethodException e2) {
112: try {
113: m = this .getClass().getMethod(
114: "tf",
115: new Class[] { c1.getClass(),
116: c2.getClass().getSuperclass() });
117: } catch (NoSuchMethodException e3) {
118: m = this .getClass().getMethod(
119: "tf",
120: new Class[] {
121: c1.getClass().getSuperclass(),
122: c2.getClass().getSuperclass() });
123: }
124: }
125: }
126:
127: res = (Command) m.invoke(this , new Object[] { c1, c2 });
128:
129: return res;
130: }
131:
132: /*
133: * Take care of Text commands - AddBlock - DelBlock
134: */
135:
136: /**
137: * AddBlock
138: */
139: public Command tf(AddBlock c1, AddBlock c2) throws Exception {
140: int s1 = c1.getInsertPoint();
141: int l1 = c1.getSize();
142: int s2 = c2.getInsertPoint();
143: int l2 = c2.getSize();
144:
145: if (s1 < s2) {
146: return c1;
147: } else {
148: // s1 >= s2
149: if (s1 > s2) {
150: AddBlock c = (AddBlock) ObjectCloner.deepCopy(c1);
151: c.slide(l2);
152:
153: return c;
154: } else {
155: // s1 == s2
156: if (c1.equals(c2)) {
157: return new Id(c1, ws);
158: } else {
159: // o1 == 02
160: //Logger.getLogger("blurp").info("conflict
161: // addblock/addblock, c1:" + c1.toStringVerbose() + ", c2:"
162: // + c2.toStringVerbose());
163: //Logger.getLogger("blurp").info("ticket a1:" +
164: // c1.getTicket() + ",a2:" + c2.getTicket());
165: // generate DelBlock (to remove block added before)
166: DelBlock d = new DelBlock(c2, ws);
167:
168: // generate AddBlock (add block merging addblocks from c1
169: // and c2);
170: ArrayList contents = new ArrayList();
171: AddBlock cBefore = (AddBlock) c1.max(c2);
172: AddBlock cAfter = (AddBlock) c1.min(c2);
173: assert (!cBefore.equals(cAfter)) : "wizzz";
174: contents.add(CONFLICT_BLOC_START
175: + CONFLICT_TYPE_ADD_ADD); // +
176: // "\n");
177:
178: for (Iterator i = cBefore.getContent().iterator(); i
179: .hasNext();) {
180: contents.add(CONFLICT_BLOC_PADDING
181: + ((String) i.next()));
182: }
183:
184: contents.add(CONFLICT_BLOC_SPLIT
185: + cBefore.getWsName()
186: + CONFLICT_BLOC_ORIGINE_SEPARATOR
187: + cAfter.getWsName()); // +
188: // "\n");
189:
190: for (Iterator i = cAfter.getContent().iterator(); i
191: .hasNext();) {
192: contents.add(CONFLICT_BLOC_PADDING
193: + ((String) i.next()));
194: }
195:
196: contents.add(CONFLICT_BLOC_END); // + "\n");
197:
198: AddBlock a = new AddBlock(c1.getPath(), ws, c1
199: .getInsertPoint(), contents);
200: a.setConflict(true);
201:
202: Macro m = new Macro(c1, ws);
203: m.setCommand(d, 1);
204: m.setCommand(a, 2);
205:
206: return m;
207: }
208: }
209: }
210: }
211:
212: public Command tf(AddBlock c1, DelBlock c2) throws Exception {
213: int s1 = c1.getInsertPoint();
214: int s2 = c2.getDeletePoint();
215: int e2 = (s2 + c2.getSize()) - 1;
216:
217: if (s1 <= s2) { //PATCH
218:
219: return c1;
220: } else { // s1>=s2
221:
222: if (s1 > e2) {
223: AddBlock clone = (AddBlock) ObjectCloner.deepCopy(c1);
224: clone.slide(-c2.getSize());
225:
226: return clone;
227: } else { // s1>=s2 && s1<=e2
228:
229: // conflit (le point d'insertion a ete efface)
230: // generate HunkDel (remove block added before)
231: ArrayList contents = new ArrayList();
232: contents.add(CONFLICT_BLOC_START
233: + CONFLICT_TYPE_REMOVE_ADD); // +
234: // "\n");
235:
236: for (Iterator i = c2.getOldContent().iterator(); i
237: .hasNext();) {
238: contents.add(CONFLICT_BLOC_PADDING
239: + ((String) i.next()));
240: }
241:
242: contents.add(CONFLICT_BLOC_SPLIT + c2.getWsName()
243: + CONFLICT_BLOC_ORIGINE_SEPARATOR
244: + c1.getWsName()); // +
245: // "\n");
246:
247: for (Iterator i = c1.getContent().iterator(); i
248: .hasNext();) {
249: contents.add(CONFLICT_BLOC_PADDING
250: + ((String) i.next()));
251: }
252:
253: contents.add(CONFLICT_BLOC_END); // + "\n");
254:
255: AddBlock a = new AddBlock(c2.getPath(), ws, c2
256: .getDeletePoint(), contents);
257:
258: //-1 ???
259: a.setTicket(c1.getTicket());
260: a.setConflict(true);
261:
262: return a;
263: }
264: }
265: }
266:
267: /**
268: * DelBlock
269: */
270: public Command tf(DelBlock c1, DelBlock c2) throws Exception {
271: int s1 = c1.getDeletePoint();
272: int e1 = (s1 + c1.getSize()) - 1;
273: int s2 = c2.getDeletePoint();
274: int e2 = (s2 + c2.getSize()) - 1;
275: DelBlock clone = (DelBlock) ObjectCloner.deepCopy(c1);
276:
277: if (s1 < s2) { // block de c1 devant celui de c2
278:
279: if (e1 < s2) { // blocks disjoints
280:
281: // return DelBlock[s1;e1]
282: return c1;
283: } else { // e1 >= s2
284:
285: if (e1 < e2) {
286: // return DelBlock[s1;s2[
287: clone.cutTailFrom(e1 - s2 + 1);
288:
289: return clone;
290: } else { // e1 >= e2
291:
292: // return DelBlock[s1;s2[;DelBlock]e2;e1] (slide le deuxieme
293: // block)
294: clone.cutTailFrom(e1 - s2 + 1);
295:
296: if (e1 == e2) {
297: return clone;
298: } else {
299: DelBlock clone2 = (DelBlock) ObjectCloner
300: .deepCopy(c1);
301: clone2.cutHeadTo(s2 - s1);
302: clone2.cutTailFrom(e1 - e2);
303: clone2.slide(-(s2 - s1));
304: assert (clone2.getSize() == c2.getSize()) : "die bitch...\n"
305: + "clone2:"
306: + clone2.toString()
307: + "\n"
308: + "c2:" + c2.toString();
309:
310: Command cmd = null;
311:
312: if (clone2.getOldContent().equals(
313: c2.getOldContent())) {
314: cmd = new Id(clone2, ws);
315: } else {
316: cmd = new NoOp(clone2, ws);
317: }
318:
319: DelBlock clone3 = (DelBlock) ObjectCloner
320: .deepCopy(c1);
321: clone3.cutHeadTo(e2 - s1 + 1);
322: clone3.slide(-(e2 - s1 + 1));
323:
324: Macro m1 = new Macro(c1, ws);
325: m1.setCommand(cmd, 1);
326: m1.setCommand(clone3, 2);
327:
328: Macro m = new Macro(c1, ws);
329: m.setCommand(clone, 1);
330: m.setCommand(m1, 2);
331:
332: return m;
333: }
334: }
335: }
336: } else { // s1 >= s2
337:
338: if (s1 > e2) {
339: // // block de c2 devant celui de c1 et blocks disjoints
340: // return DelBlock[s1+c2.getSize();e1+c2.getSize()];
341: clone.slide(-c2.getSize());
342:
343: return clone;
344: } else { // s1 <= e2
345:
346: if (e1 < e2) {
347: // return DelBlock[] = NoOp();
348: DelBlock clone2 = (DelBlock) ObjectCloner
349: .deepCopy(c2);
350: clone2.cutHeadTo(s1 - s2);
351: clone2.cutTailFrom(e2 - e1);
352: clone2.slide(-(s1 - s2));
353: assert (clone2.getSize() == c1.getSize()) : "turlu...\n"
354: + "clone2:"
355: + clone2.toString()
356: + "\n"
357: + "c1:" + c1.toString();
358:
359: if (clone2.getOldContent().equals(
360: c1.getOldContent())) {
361: return new Id(clone2, ws);
362: } else {
363: return new NoOp(clone2, ws);
364: }
365:
366: //return new NoOp(c1);
367: } else { //e1 >= e2
368:
369: if (e1 == e2) { // c1 equals c2
370:
371: return new Id(c1, ws);
372: } else { // e1>e2
373:
374: // return DelBlock[e2;e1]
375: clone.cutHeadTo(e2 - s1 + 1);
376:
377: // clone.slide(-c2.getSize()+(e2-s1+1));
378: clone.slide(-c2.getSize());
379:
380: return clone;
381: }
382: }
383: }
384: }
385: }
386:
387: public Command tf(DelBlock c1, AddBlock c2) throws Exception {
388: int s1 = c1.getDeletePoint();
389: int e1 = (s1 + c1.getSize()) - 1;
390: int s2 = c2.getInsertPoint();
391:
392: if (s1 >= s2) {
393: DelBlock clone = (DelBlock) ObjectCloner.deepCopy(c1);
394: clone.slide(c2.getSize());
395:
396: return clone;
397: } else { // s1<=s2
398:
399: if (e1 < s2) {
400: return c1;
401: } else {
402: // conflit (le point d'insertion aurait pu etre efface)
403: // generate DelBlock (to remove block added before)
404: DelBlock d = new DelBlock(c2, ws);
405:
406: // conflit (le point d'insertion a ete efface)
407: ArrayList contents = new ArrayList();
408: contents.add(CONFLICT_BLOC_START
409: + CONFLICT_TYPE_REMOVE_ADD); // +
410: // "\n");
411:
412: for (Iterator i = c1.getOldContent().iterator(); i
413: .hasNext();) {
414: contents.add(CONFLICT_BLOC_PADDING
415: + ((String) i.next()));
416: }
417:
418: contents.add(CONFLICT_BLOC_SPLIT + c1.getWsName()
419: + CONFLICT_BLOC_ORIGINE_SEPARATOR
420: + c2.getWsName()); // +
421: // "\n");
422:
423: for (Iterator i = c2.getContent().iterator(); i
424: .hasNext();) {
425: contents.add(CONFLICT_BLOC_PADDING
426: + ((String) i.next()));
427: }
428:
429: contents.add(CONFLICT_BLOC_END); // + "\n");
430:
431: AddBlock a = new AddBlock(c2.getPath(), ws, c1
432: .getDeletePoint(), contents);
433: a.setConflict(true);
434:
435: Macro m = new Macro(c1, ws);
436: Macro m2 = new Macro(c1, ws);
437: m.setCommand(m2, 1);
438: m2.setCommand(d, 1);
439: m2.setCommand(c1, 2);
440: m.setCommand(a, 2);
441: m.setTicket(c1.getTicket());
442:
443: return m;
444: }
445: }
446: }
447: }
|