Index: trunk/MagicSoft/Mars/mbase/MEvtLoop.cc
===================================================================
--- trunk/MagicSoft/Mars/mbase/MEvtLoop.cc	(revision 1479)
+++ trunk/MagicSoft/Mars/mbase/MEvtLoop.cc	(revision 1481)
@@ -70,9 +70,10 @@
 #include "MEvtLoop.h"
 
-#include <time.h>
-#include <fstream.h>     // ofstream, SavePrimitive
+#include <time.h>           // time_t
+#include <fstream.h>        // ofstream, SavePrimitive
 #include <iostream.h>
 
-#include <TSystem.h>
+#include <TFile.h>          // gFile
+#include <TSystem.h>        // gSystem
 #include <TStopwatch.h>
 #include <TGProgressBar.h>
@@ -352,31 +353,162 @@
 // to a macro. In the original root implementation it is used to write
 // gui elements to a macro-file.
-
 //
 void MEvtLoop::SavePrimitive(ofstream &out, Option_t *)
 {
-    fParList->SavePrimitive(out);
+    if (HasDuplicateNames("MEvtLoop::SavePrimitive"))
+    {
+        out << "   // !" << endl;
+        out << "   // ! WARNING - Your eventloop (MParList, MTaskList, ...) contains more than" << endl;
+        out << "   // ! one object (MParContainer, MTask, ...) with the same name. The created macro" << endl;
+        out << "   // ! may need manual intervention before it can be used." << endl;
+        out << "   // !" << endl;
+        out << endl;
+    }
+
+    if (fParList)
+        fParList->SavePrimitive(out);
 
     out << "   MEvtLoop evtloop;" << endl;
-    out << "   evtloop.SetParList(&" << ToLower(fParList->GetName()) << ");" << endl;
+    if (fParList)
+        out << "   evtloop.SetParList(&" << ToLower(fParList->GetName()) << ");" << endl;
+    else
+        out << "   // fParList empty..." << endl;
     out << "   if (!evtloop.Eventloop())" << endl;
     out << "      return;" << endl;
 }
 
+// --------------------------------------------------------------------------
+//
+// Get a list of all conmtainer names which are somehow part of the
+// eventloop. Chack for duplicate members and print a warning if
+// duplicates are found. Return kTRUE if duplicates are found, otherwise
+// kFALSE;
+//
+Bool_t MEvtLoop::HasDuplicateNames(TObjArray &arr, const TString txt) const
+{
+    arr.Sort();
+
+    TIter Next(&arr);
+    TObject *obj;
+    TString name;
+    Bool_t found = kFALSE;
+    while ((obj=Next()))
+    {
+        if (name==obj->GetName())
+        {
+            if (!found)
+            {
+                *fLog << warn << endl;
+                *fLog << " ! WARNING (" << txt << ")" << endl;
+                *fLog << " ! Your eventloop (MParList, MTaskList, ...) contains more than" << endl;
+                *fLog << " ! one object (MParContainer, MTask, ...) with the same name." << endl;
+                *fLog << " ! Creating a macro from it using MEvtLoop::MakeMacro may create" << endl;
+                *fLog << " ! a macro which needs manual intervention before it can be used." << endl;
+                found = kTRUE;
+            }
+            *fLog << " ! Please rename: " << obj->GetName() << endl;
+        }
+        name = obj->GetName();
+    }
+
+    return found;
+}
+
+// --------------------------------------------------------------------------
+//
+// Get a list of all conmtainer names which are somehow part of the
+// eventloop. Chack for duplicate members and print a warning if
+// duplicates are found. Return kTRUE if duplicates are found, otherwise
+// kFALSE;
+//
+Bool_t MEvtLoop::HasDuplicateNames(const TString txt) const
+{
+    if (!fParList)
+        return kFALSE;
+
+    TObjArray list;
+    list.SetOwner();
+
+    fParList->GetNames(list);
+
+    return HasDuplicateNames(list, txt);
+}
+
+// --------------------------------------------------------------------------
+//
+// Reads a saved eventloop from a file. The default name is "Evtloop".
+// Therefor an open file must exist (See TFile for more information)
+//
+//  eg:
+//        TFile file("myfile.root", "READ");
+//        MEvtLoop evtloop;
+//        evtloop.Read();
+//        evtloop.MakeMacro("mymacro");
+//
 Int_t MEvtLoop::Read(const char *name)
 {
+    if (!gFile)
+    {
+        *fLog << err << "MEvtloop::Read: No file found. Please create a TFile first." << endl;
+        return 0;
+    }
+
+    if (!gFile->IsOpen())
+    {
+        *fLog << err << "MEvtloop::Read: File not open. Please open the TFile first." << endl;
+        return 0;
+    }
+
     Int_t n = 0;
     TObjArray list;
 
     n += TObject::Read(name);
+
+    if (n==0)
+    {
+        *fLog << err << "MEvtloop::Read: No objects read." << endl;
+        return 0;
+    }
+
     n += list.Read((TString)name+"_names");
 
     fParList->SetNames(list);
 
+    HasDuplicateNames(list, "MEvtLoop::Read");
+
     return n;
 }
 
+// --------------------------------------------------------------------------
+//
+// Writes a eventloop to a file. The default name is "Evtloop".
+// Therefor an open file must exist (See TFile for more information)
+//
+//  eg:
+//        TFile file("myfile.root", "RECREATE");
+//        MEvtLoop evtloop;
+//        evtloop.Write();
+//        file.Close();
+//
 Int_t MEvtLoop::Write(const char *name, Int_t option, Int_t bufsize)
 {
+    if (!gFile)
+    {
+        *fLog << err << "MEvtloop::Write: No file found. Please create a TFile first." << endl;
+        return 0;
+    }
+
+    if (!gFile->IsOpen())
+    {
+        *fLog << err << "MEvtloop::Write: File not open. Please open the TFile first." << endl;
+        return 0;
+    }
+
+    if (!gFile->IsWritable())
+    {
+        *fLog << err << "MEvtloop::Write: File not writable." << endl;
+        return 0;
+    }
+
     Int_t n = 0;
 
@@ -386,6 +518,15 @@
     fParList->GetNames(list);
 
+    n += TObject::Write(name, option, bufsize);
+
+    if (n==0)
+    {
+        *fLog << err << "MEvtloop::Read: No objects written." << endl;
+        return 0;
+    }
+
     n += list.Write((TString)name+"_names", kSingleKey);
-    n += TObject::Write(name, option, bufsize);
+
+    HasDuplicateNames(list, "MEvtLoop::Write");
 
     return n;
Index: trunk/MagicSoft/Mars/mbase/MEvtLoop.h
===================================================================
--- trunk/MagicSoft/Mars/mbase/MEvtLoop.h	(revision 1479)
+++ trunk/MagicSoft/Mars/mbase/MEvtLoop.h	(revision 1481)
@@ -27,4 +27,7 @@
 
     enum { kIsOwner = BIT(14) };
+
+    Bool_t HasDuplicateNames(const TString txt) const;
+    Bool_t HasDuplicateNames(TObjArray &arr, const TString txt) const;
 
 public:
Index: trunk/MagicSoft/Mars/mbase/MFilter.cc
===================================================================
--- trunk/MagicSoft/Mars/mbase/MFilter.cc	(revision 1479)
+++ trunk/MagicSoft/Mars/mbase/MFilter.cc	(revision 1481)
@@ -98,2 +98,7 @@
     return kTRUE;
 }
+
+TString MFilter::GetRule() const
+{
+    return "<GetRule not available for " + fName + ">";
+}
Index: trunk/MagicSoft/Mars/mbase/MFilter.h
===================================================================
--- trunk/MagicSoft/Mars/mbase/MFilter.h	(revision 1479)
+++ trunk/MagicSoft/Mars/mbase/MFilter.h	(revision 1481)
@@ -19,4 +19,6 @@
     virtual Bool_t PostProcess();
 
+    virtual TString GetRule() const;
+
     ClassDef(MFilter, 0)		// Abstract base class for the filters
 };
Index: trunk/MagicSoft/Mars/mbase/MFilterList.cc
===================================================================
--- trunk/MagicSoft/Mars/mbase/MFilterList.cc	(revision 1479)
+++ trunk/MagicSoft/Mars/mbase/MFilterList.cc	(revision 1481)
@@ -31,4 +31,6 @@
 #include "MFilterList.h"
 
+#include <fstream.h>
+
 #include <TString.h>
 
@@ -53,6 +55,9 @@
 //      lor, ||  : is a logical or
 //
-MFilterList::MFilterList(const char *type)
-{
+MFilterList::MFilterList(const char *type, const char *name, const char *title)
+{
+    fName  = name  ? name  : "MFilterList";
+    fTitle = title ? title : "List combining filters logically.";
+
     fFilterType = kEAnd;
 
@@ -236,10 +241,60 @@
 void MFilterList::Print(Option_t *opt) const
 {
+    *fLog << all << GetRule(opt) << flush;
+}
+
+// --------------------------------------------------------------------------
+//
+// Implementation of SavePrimitive. Used to write the call to a constructor
+// to a macro. In the original root implementation it is used to write
+// gui elements to a macro-file.
+//
+void MFilterList::StreamPrimitive(ofstream &out) const
+{
+    out << "   MFilterList " << ToLower(fName) << "(\"";
+
+    switch (fFilterType)
+    {
+    case kEAnd:
+        out << "&";
+        break;
+
+    case kEOr:
+        out  << "|";
+        break;
+
+    case kEXor:
+        out  << "^";
+        break;
+
+    case kELAnd:
+        out << "&&";
+        break;
+
+    case kELOr:
+        out << "||";
+        break;
+    }
+
+    out << fName << "\", \"" << fName << "\", \"" << fTitle << "\");" << endl << endl;
+
+    TIter Next(&fFilters);
+
+    TObject *cont = NULL;
+    while ((cont=Next()))
+    {
+        cont->SavePrimitive(out, "");
+
+        out << "   " << ToLower(fName) << ".AddToList(&";
+        out << ToLower(cont->GetName()) << ");" << endl << endl;
+    }
+}
+
+TString MFilterList::GetRule(Option_t *opt) const
+{
     TString str(opt);
     const Bool_t verbose = str.Contains("V", TString::kIgnoreCase);
 
-    //*fLog << all << "(" << GetName() << "=" << (int)fFilterType << ")";
-
-    *fLog << all << "(";
+    TString ret = "(";
 
     TIter Next(&fFilters);
@@ -251,10 +306,7 @@
     //
     if (!filter)
-    {
-        *fLog << "<empty>)" << flush;
-        return;
-    }
-
-    filter->Print();
+        return "<empty>";
+
+    ret += filter->GetRule();
 
     while ((filter=(MFilter*)Next()))
@@ -263,28 +315,27 @@
         {
         case kEAnd:
-            *fLog << (verbose?" and ":" & ");
+            ret += (verbose?" and ":" & ");
             break;
 
         case kEOr:
-            *fLog << (verbose?" or ":" | ");
+            ret += (verbose?" or ":" | ");
             break;
 
         case kEXor:
-            *fLog << (verbose?" xor ":" ^ ");
+            ret += (verbose?" xor ":" ^ ");
             break;
 
         case kELAnd:
-            *fLog << (verbose?" land ":" && ");
+            ret += (verbose?" land ":" && ");
             break;
 
         case kELOr:
-            *fLog << (verbose?" lor ":" || ");
+            ret += (verbose?" lor ":" || ");
             break;
         }
 
-        filter->Print();
-    }
-
-    *fLog << ")" << flush;
-}
-
+        ret += filter->GetRule();
+    }
+
+    return ret+")";
+}
Index: trunk/MagicSoft/Mars/mbase/MFilterList.h
===================================================================
--- trunk/MagicSoft/Mars/mbase/MFilterList.h	(revision 1479)
+++ trunk/MagicSoft/Mars/mbase/MFilterList.h	(revision 1481)
@@ -29,6 +29,8 @@
     enum { kIsOwner = BIT(14) };
 
+    void StreamPrimitive(ofstream &out) const;
+
 public:
-    MFilterList(const char *type="&&");
+    MFilterList(const char *type="&&", const char *name=NULL, const char *title=NULL);
     MFilterList(MFilterList &ts);
     ~MFilterList()
@@ -48,6 +50,7 @@
 
     void Print(Option_t *opt = "") const;
+    TString GetRule(Option_t *opt="") const;
 
-    ClassDef(MFilterList, 0)		// List to combine several filters logically
+    ClassDef(MFilterList, 1)		// List to combine several filters logically
 };
 
Index: trunk/MagicSoft/Mars/mbase/MTask.h
===================================================================
--- trunk/MagicSoft/Mars/mbase/MTask.h	(revision 1479)
+++ trunk/MagicSoft/Mars/mbase/MTask.h	(revision 1481)
@@ -24,5 +24,5 @@
     TList *fListOfBranches; //! List of Branch names for auto enabeling scheme
 
-    const MFilter *fFilter; // Filter for conditional task execution
+    MFilter *fFilter;       // Filter for conditional task execution
 
     Bool_t fIsPreprocessed; //! Indicates the success of the PreProcessing (set by MTaskList)
@@ -68,5 +68,5 @@
     virtual ~MTask();
 
-    void SetFilter(const MFilter *filter) { fFilter=filter; }
+    void SetFilter(MFilter *filter) { fFilter=filter; }
     const MFilter *GetFilter() const      { return fFilter; }
     virtual void PrintStatistics(const Int_t lvl=0) const;
