001: /***************************************************************
002: * This file is part of the [fleXive](R) project.
003: *
004: * Copyright (c) 1999-2007
005: * UCS - unique computing solutions gmbh (http://www.ucs.at)
006: * All rights reserved
007: *
008: * The [fleXive](R) project is free software; you can redistribute
009: * it and/or modify it under the terms of the GNU General Public
010: * License as published by the Free Software Foundation;
011: * either version 2 of the License, or (at your option) any
012: * later version.
013: *
014: * The GNU General Public License can be found at
015: * http://www.gnu.org/copyleft/gpl.html.
016: * A copy is found in the textfile GPL.txt and important notices to the
017: * license from the author are found in LICENSE.txt distributed with
018: * these libraries.
019: *
020: * This library is distributed in the hope that it will be useful,
021: * but WITHOUT ANY WARRANTY; without even the implied warranty of
022: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
023: * GNU General Public License for more details.
024: *
025: * For further information about UCS - unique computing solutions gmbh,
026: * please see the company website: http://www.ucs.at
027: *
028: * For further information about [fleXive](R), please see the
029: * project website: http://www.flexive.org
030: *
031: *
032: * This copyright notice MUST APPEAR in all copies of the file!
033: ***************************************************************/package com.flexive.war.beans.admin.structure;
034:
035: import com.flexive.shared.scripting.FxScriptInfo;
036: import com.flexive.shared.scripting.FxScriptEvent;
037: import com.flexive.shared.scripting.FxScriptMappingEntry;
038: import com.flexive.shared.exceptions.FxEntryExistsException;
039: import com.flexive.shared.exceptions.FxNotFoundException;
040: import com.flexive.shared.CacheAdmin;
041: import com.flexive.shared.FxSharedUtils;
042: import com.flexive.shared.structure.FxType;
043: import com.flexive.shared.structure.FxAssignment;
044:
045: import java.util.*;
046: import java.io.Serializable;
047: import java.text.Collator;
048:
049: /**
050: * Conveniently wraps script mappings to simplify GUI Manipulaiton.
051: *
052: * @author Gerhard Glos (gerhard.glos@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
053: */
054: public class ScriptListWrapper {
055: public final static int ID_SCRIPT_REMOVED = -1;
056: public final static int ID_SCRIPT_ADDED = -2;
057: public final static int ID_SCRIPT_UPDATED = -3;
058: public final static int SORT_STATUS_UNSORTED = 0;
059: public final static int SORT_STATUS_ASCENDING = 1;
060: public final static int SORT_STATUS_DESCENDING = 2;
061: private int sortStatusScriptInfo = -1;
062: private int sortStatusEvent = -1;
063:
064: public class ScriptListEntry {
065: private int id;
066: private FxScriptInfo scriptInfo = null;
067: private FxScriptEvent scriptEvent = null;
068: private boolean derived = false;
069: private boolean derivedUsage = false;
070: private long derivedFrom = -1;
071: private boolean active = false;
072:
073: public ScriptListEntry(int id, FxScriptInfo scriptInfo,
074: FxScriptEvent scriptEvent, boolean derived,
075: long derivedFrom, boolean derivedUsage, boolean active) {
076: this .id = id;
077: this .scriptInfo = scriptInfo;
078: this .scriptEvent = scriptEvent;
079: this .derived = derived;
080: this .derivedFrom = derivedFrom;
081: this .derivedUsage = derivedUsage;
082: this .active = active;
083: }
084:
085: public int getId() {
086: return id;
087: }
088:
089: private void setId(int id) {
090: this .id = id;
091: }
092:
093: public FxScriptInfo getScriptInfo() {
094: return scriptInfo;
095: }
096:
097: public FxScriptEvent getScriptEvent() {
098: return scriptEvent;
099: }
100:
101: public boolean isDerived() {
102: return derived;
103: }
104:
105: public void setDerived(boolean derived) {
106: this .derived = derived;
107: }
108:
109: public boolean isDerivedUsage() {
110: return derivedUsage;
111: }
112:
113: public void setDerivedUsage(boolean derivedUsage) {
114: this .derivedUsage = derivedUsage;
115: }
116:
117: public long getDerivedFrom() {
118: return derivedFrom;
119: }
120:
121: public void setDerivedFrom(long derivedFrom) {
122: this .derivedFrom = derivedFrom;
123: }
124:
125: public boolean isActive() {
126: return active;
127: }
128:
129: public void setActive(boolean active) {
130: this .active = active;
131: }
132: }
133:
134: private List<ScriptListEntry> scriptList = null;
135: private int ctr = 0;
136: private Comparator<ScriptListEntry> scriptComparator = new ScriptInfoSorter();
137: private Comparator<ScriptListEntry> eventComparator = new ScriptEventSorter();
138:
139: /**
140: * Constructs a new script list wrapper
141: *
142: * @param id the id of the type or assignment
143: * @param isType if the id is from a type or assignment
144: */
145: ScriptListWrapper(long id, boolean isType) {
146: scriptList = buildScriptList(id, isType);
147: sortByScripts();
148: }
149:
150: private List<ScriptListEntry> buildScriptList(long id,
151: boolean isType) {
152: //determine if type or assignment are derived
153: boolean isDerived = false;
154: if (isType) {
155: FxType type = CacheAdmin.getEnvironment().getType(id);
156: isDerived = type.isDerived();
157: } else {
158: FxAssignment ass = CacheAdmin.getEnvironment()
159: .getAssignment(id);
160: isDerived = ass.isDerivedAssignment();
161: }
162: List<ScriptListEntry> list = new ArrayList<ScriptListEntry>();
163:
164: //set remaining propterties
165: for (FxScriptInfo s : CacheAdmin.getEnvironment().getScripts())
166: for (FxScriptMappingEntry e : isType ? CacheAdmin
167: .getFilteredEnvironment().getScriptMapping(
168: s.getId()).getMappedTypes() : CacheAdmin
169: .getFilteredEnvironment().getScriptMapping(
170: s.getId()).getMappedAssignments()) {
171: FxScriptMappingEntry debug = e;
172: //determine if script is active and if it should be derived
173: if (e.getId() == id && s.getId() == e.getScriptId()) {
174: list.add(new ScriptListEntry(ctr++, s, e
175: .getScriptEvent(), false, -1, e
176: .isDerivedUsage(), e.isActive()));
177: }
178: //determine if script is derived and from which id
179: else if (isDerived && e.isDerivedUsage()
180: && s.getId() == e.getScriptId()) {
181: for (long derivedId : e.getDerivedIds()) {
182: if (id == derivedId) {
183: list.add(new ScriptListEntry(ctr++, s, e
184: .getScriptEvent(), true, e.getId(),
185: e.isDerivedUsage(), e.isActive()));
186: break;
187: }
188: }
189: }
190: }
191: return list;
192: }
193:
194: /**
195: * builds the delta to the original scriptMapping. Returns a List of ScriptListEntry objects,
196: * where the id is set to ScriptListWrapper.ID_SCRIPT_REMOVED for scripts that where removed from
197: * the script list and where the id is set to ScriptListWrapper.ID_SCRIPT_ADDED for scripts that
198: * where added to the script list. ID_SCRIPT_UPDATED for scripts that have been updated.
199: *
200: * @param id the id of the type or assignment for the script mapping
201: * @param isType if the script mapping is from a type or assignment
202: * @return a list of ScriptEntry objects which have changed in the script list relative to
203: * the original scriptMapping.
204: */
205:
206: public List<ScriptListEntry> getDelta(long id, boolean isType) {
207: List<ScriptListEntry> delta = new ArrayList<ScriptListEntry>();
208: List<ScriptListEntry> original = buildScriptList(id, isType);
209: for (ScriptListEntry s : original) {
210: if (!hasEntry(s)) {
211: s.setId(ID_SCRIPT_REMOVED);
212: delta.add(s);
213: }
214: }
215:
216: for (ScriptListEntry s : scriptList) {
217: if (!hasEntry(original, s)) {
218: delta.add(new ScriptListEntry(ID_SCRIPT_ADDED, s
219: .getScriptInfo(), s.getScriptEvent(), s
220: .isDerived(), s.getDerivedFrom(),
221: s.derivedUsage, s.isActive()));
222: }
223: }
224:
225: for (ScriptListEntry s : scriptList)
226: if (!hasEntry(delta, s)) {
227: //TODO: check if value has really changed versus the original before marking UPDATED ->would increase computing time but decrease DB accesses
228: delta.add(new ScriptListEntry(ID_SCRIPT_UPDATED, s
229: .getScriptInfo(), s.getScriptEvent(), s
230: .isDerived(), s.getDerivedFrom(),
231: s.derivedUsage, s.isActive()));
232: }
233:
234: return delta;
235: }
236:
237: public List<ScriptListEntry> getScriptList() {
238: return scriptList;
239: }
240:
241: public Map<ScriptListEntry, Boolean> hasDoubleEntry() {
242: return new HashMap<ScriptListEntry, Boolean>() {
243: public Boolean getObject(Object key) {
244: int ctr = 0;
245: for (ScriptListEntry le : scriptList) {
246: if (le.getScriptEvent().getId() == ((ScriptListEntry) key)
247: .getScriptEvent().getId()
248: && le.getScriptInfo().getId() == ((ScriptListEntry) key)
249: .getScriptInfo().getId())
250: ctr++;
251: if (ctr > 1)
252: return true;
253: }
254: return false;
255: }
256: };
257: }
258:
259: /**
260: * checks the script list for a script list entry with matching script id and event.
261: *
262: * @param key a script list entry
263: * @return true if another script list entry with matching script id and event was found
264: */
265: private boolean hasEntry(ScriptListEntry key) {
266: for (ScriptListEntry le : scriptList) {
267: if (le.getScriptEvent().getId() == key.getScriptEvent()
268: .getId()
269: && le.getScriptInfo().getId() == key
270: .getScriptInfo().getId())
271: return true;
272: }
273: return false;
274: }
275:
276: /**
277: * checks a specific script list for a script list entry with matching
278: * script id and event.
279: *
280: * @param scriptList the script list to be searched
281: * @param key a script list entry
282: * @return true if another script list entry with matching script id and event was found
283: */
284:
285: private boolean hasEntry(List<ScriptListEntry> scriptList,
286: ScriptListEntry key) {
287: for (ScriptListEntry le : scriptList) {
288: if (le.getScriptEvent().getId() == key.getScriptEvent()
289: .getId()
290: && le.getScriptInfo().getId() == key
291: .getScriptInfo().getId())
292: return true;
293: }
294: return false;
295: }
296:
297: public void add(long scriptInfo, long scirptEvent,
298: boolean derivedUsage, boolean active)
299: throws FxEntryExistsException, FxNotFoundException {
300: ScriptListEntry e = new ScriptListEntry(ctr++, CacheAdmin
301: .getEnvironment().getScript(scriptInfo), FxScriptEvent
302: .getById(scirptEvent), false, -1, derivedUsage, active);
303: if (!hasEntry(e)) {
304: scriptList.add(e);
305: sortStatusScriptInfo = SORT_STATUS_UNSORTED;
306: sortStatusEvent = SORT_STATUS_UNSORTED;
307: } else
308: throw new FxEntryExistsException(e.getScriptInfo()
309: .getName()
310: + ":" + e.getScriptEvent().getName(),
311: "ex.scriptListWrapper.entryExists", e
312: .getScriptInfo().getName()
313: + ":" + e.getScriptEvent().getName());
314: }
315:
316: public void remove(int entryId) {
317: ScriptListEntry entry = null;
318: for (ScriptListEntry e : scriptList) {
319: if (e.getId() == entryId) {
320: entry = e;
321: break;
322: }
323: }
324: scriptList.remove(entry);
325: }
326:
327: public void sortByScripts() {
328: Collections.sort(scriptList, scriptComparator);
329: if (sortStatusScriptInfo == SORT_STATUS_UNSORTED)
330: sortStatusScriptInfo = SORT_STATUS_ASCENDING;
331: else if (sortStatusScriptInfo == SORT_STATUS_ASCENDING)
332: sortStatusScriptInfo = SORT_STATUS_DESCENDING;
333: else
334: sortStatusScriptInfo = SORT_STATUS_ASCENDING;
335:
336: sortStatusEvent = SORT_STATUS_UNSORTED;
337: }
338:
339: public void sortByEvents() {
340: Collections.sort(scriptList, eventComparator);
341: if (sortStatusEvent == SORT_STATUS_UNSORTED)
342: sortStatusEvent = SORT_STATUS_ASCENDING;
343: else if (sortStatusEvent == SORT_STATUS_ASCENDING)
344: sortStatusEvent = SORT_STATUS_DESCENDING;
345: else
346: sortStatusEvent = SORT_STATUS_ASCENDING;
347:
348: sortStatusScriptInfo = SORT_STATUS_UNSORTED;
349: }
350:
351: public int getSortStatusScriptInfo() {
352: return sortStatusScriptInfo;
353: }
354:
355: public void setSortStatusScriptInfo(int sortStatusScriptInfo) {
356: this .sortStatusScriptInfo = sortStatusScriptInfo;
357: }
358:
359: public int getSortStatusEvent() {
360: return sortStatusEvent;
361: }
362:
363: public void setSortStatusEvent(int sortStatusEvent) {
364: this .sortStatusEvent = sortStatusEvent;
365: }
366:
367: /**
368: * compares script list entries, priorizes the script name and if equal the event name
369: */
370: private class ScriptInfoSorter implements
371: Comparator<ScriptListEntry>, Serializable {
372: private final Collator collator = FxSharedUtils.getCollator();
373:
374: public int compare(ScriptListEntry o1, ScriptListEntry o2) {
375: int multiplicator = 1;
376: if (sortStatusScriptInfo == SORT_STATUS_ASCENDING)
377: multiplicator = -1;
378: int c1 = this .collator.compare(
379: o1.getScriptInfo().getName(), o2.getScriptInfo()
380: .getName());
381: if (c1 != 0)
382: return c1 * multiplicator;
383: else
384: return multiplicator
385: * this .collator.compare(o1.getScriptEvent()
386: .getName(), o2.getScriptEvent()
387: .getName());
388: }
389: }
390:
391: /**
392: * compares script list entries, priorizes the script event name and if equal the script name
393: */
394: private class ScriptEventSorter implements
395: Comparator<ScriptListEntry>, Serializable {
396: private final Collator collator = FxSharedUtils.getCollator();
397:
398: public int compare(ScriptListEntry o1, ScriptListEntry o2) {
399: int multiplicator = 1;
400: if (sortStatusEvent == SORT_STATUS_ASCENDING)
401: multiplicator = -1;
402: int c1 = this .collator.compare(o1.getScriptEvent()
403: .getName(), o2.getScriptEvent().getName());
404: if (c1 != 0)
405: return c1 * multiplicator;
406: else
407: return multiplicator
408: * this .collator.compare(o1.getScriptInfo()
409: .getName(), o2.getScriptInfo()
410: .getName());
411: }
412: }
413:
414: /* alternative Constructor for FxType.getScriptsView()
415: ScriptListWrapper(Map<FxScriptInfo, List<FxScriptEvent>> scriptMap) {
416: scriptList = new ArrayList<ScriptListEntry>();
417: for (FxScriptInfo s: scriptMap.keySet()) {
418: for (FxScriptEvent event : scriptMap.get(s)) {
419: scriptList.add(new ScriptListEntry(ctr++, s,event));
420: }
421: }
422: sortByScripts();
423: }
424: */
425: /*
426: private List<ScriptListEntry> buildScriptList(Map<FxScriptEvent, long[]> scriptMapping, long id, boolean isType) {
427: //determine if type or assignment are derived
428: boolean isDerived=false;
429: if (isType) {
430: FxType type= CacheAdmin.getEnvironment().getType(id);
431: isDerived = type.isDerived();
432: }
433: else {
434: FxAssignment ass = CacheAdmin.getEnvironment().getAssignment(id);
435: isDerived = ass.isDerivedAssignment();
436: }
437: List<ScriptListEntry> list = new ArrayList<ScriptListEntry>();
438: for (FxScriptEvent e: scriptMapping.keySet())
439: for (long scriptId: scriptMapping.get(e)) {
440: list.add(new ScriptListEntry(ctr++, CacheAdmin.getEnvironment().getScript(scriptId), e, false, -1, false, false));
441: }
442:
443: //set remaining propterties
444: for (ScriptListEntry se : list)
445: for (FxScriptMappingEntry e : CacheAdmin.getFilteredEnvironment().getScriptMapping(se.getScriptInfo().getId()).getMappedTypes() ) {
446: //determine if script is active and if it should be derived
447: if (e.getId() ==id && se.getScriptEvent().getId() == e.getScriptEvent().getId() && se.getScriptInfo().getId() == e.getScriptId()) {
448: se.setActive(e.isActive());
449: se.setDerivedUsage(e.isDerivedUsage());
450: }
451: //determine if script is derived and from which id
452: else if(isDerived && e.isDerivedUsage() && se.getScriptEvent().getId() == e.getScriptEvent().getId() && se.getScriptInfo().getId() == e.getScriptId()) {
453: for (long derivedId : e.getDerivedIds()) {
454: if (id == derivedId) {
455: se.setDerived(true);
456: se.setDerivedFrom(e.getId());
457: break;
458: }
459: }
460: }
461: }
462: return list;
463: }
464: */
465: /**
466: * Constructs a new script list wrapper
467: *
468: * @param scriptMapping the script mapping
469: * @param id the id of the type or assignment for the script mapping
470: * @param isType if the script mapping is from a type or assignment
471: */
472: /*
473: ScriptListWrapper(Map<FxScriptEvent, long[]> scriptMapping, long id, boolean isType) {
474: scriptList = buildScriptList(scriptMapping, id, isType);
475: sortByScripts();
476: }
477: */
478: /**
479: * builds the delta to the original scriptMapping. Returns a List of ScriptListEntry objects,
480: * where the id is set to ScriptListWrapper.ID_SCRIPT_REMOVED for scripts that where removed from
481: * the script list and where the id is set to ScriptListWrapper.ID_SCRIPT_ADDED for scripts that
482: * where added to the script list.
483: *
484: * @param originalScriptMapping the original scriptMapping
485: * @param id the id of the type or assignment for the script mapping
486: * @param isType if the script mapping is from a type or assignment
487: * @return a list of ScriptEntry objects which have changed in the script list relative to
488: * the original scriptMapping.
489: */
490: /*
491: public List<ScriptListEntry> getDelta(Map<FxScriptEvent, long[]> originalScriptMapping, long id, boolean isType) {
492: List<ScriptListEntry> delta = new ArrayList<ScriptListEntry>();
493: List<ScriptListEntry> original = buildScriptList(originalScriptMapping, id, isType);
494: for (ScriptListEntry s : original) {
495: if (!hasEntry(s)) {
496: s.setId(ID_SCRIPT_REMOVED);
497: delta.add(s);
498: }
499: }
500:
501: for (ScriptListEntry s : scriptList) {
502: if (!hasEntry(original, s)) {
503: delta.add(new ScriptListEntry(ID_SCRIPT_ADDED, s.getScriptInfo(), s.getScriptEvent(), s.isDerived(), s.getDerivedFrom(), s.derivedUsage, s.isActive()));
504: }
505: }
506:
507: for (ScriptListEntry s: scriptList)
508: if (!hasEntry(delta, s )) {
509: //TODO: check if value has really changed versus the original before marking UPDATED ->would increase computing time but decrease DB accesses
510: delta.add(new ScriptListEntry(ID_SCRIPT_UPDATED, s.getScriptInfo(), s.getScriptEvent(), s.isDerived(), s.getDerivedFrom(), s.derivedUsage, s.isActive()));
511: }
512:
513: return delta;
514: }
515: */
516: }
|