Hi,

I found a bug in the NSArray handling in the encoder, here is my class with a 
fix, do not use the previous version.

Samuel


> Le 9 nov. 2024 à 10:11, Samuel Pelletier via Webobjects-dev 
> <webobjects-dev@lists.apple.com> a écrit :
> 
> Hi, 
> 
> Last week I encountered a problem very similar to a previous OC case... I 
> have a report page with some user defined filter that use EOs and do the 
> fetch in background. Creating a snapshot of all possible parameter seems a 
> fragile solution since it required a very good discipline to make sure the 
> problem does not coma back... Having a way to archive or serialize an 
> EOQualifier with no exigent context dependency seems a bette solution.
> 
> After some digging in Wonder sources and list archive, I found 
> EOKeyValueArchiving but never found a complete working code using EOs. It 
> seems there is no basic implementation of delegate and support classes in 
> WOnder or elsewhere to make this works. I wrote those classes that convert 
> any EO to EOGlobalID on archiving and EOGlobalID back to EO using the 
> specified EditingContext when unarchiving.
> 
> Here si the recipe and my utility classe source for anyone that may need it. 
> I can prepare a pull request to add it to Wonder if others can confirm there 
> is nothing already in place that do that.
> 
> Regards
> 
> Samuel
> 
> 
> public class RapportRendementMatiere extends BaseRapportComponent {
>    ...
>    private KAKeyValueArchive filtersArchive = new KAKeyValueArchive();
> 
>    public actionStartingTheFetch() {
>        // build the qualifier array qualifiers in the request using Eos and 
> archive it.
>        filtersArchive.archiveObject(new ERXAndQualifier(qualifiers), 
> "qualifier");
>        // Add some other values that may require access to session or other 
> EOs
>        filtersArchive.archiveObject(dateDebutToFind(), "dateDebut");
>        filtersArchive.archiveObject(rapportMachines(), "rapportMachines");
> 
>       // Start background thread (could use ERX tasks or any other means 
> here...
>       new Thread(new Runnable() {
>               @Override
>               public void run() {
>                       ERXApplication._startRequest();
>                       try {
>                               EOEditingContext ec = ERXEC.newEditingContext();
>                               fetchRapport(ec);
>                               etat = Etat.Affiche;
>                       } finally {
>                               ERXApplication._endRequest();
>                       }
>               }
>       }).start();
>    }
> 
>    public void fetchRapport(EOEditingContext ec) {
>        // In background thread...
>        filtersArchive.setEditingContext(ec);
>        EOQualifier qualifier = filtersArchive.unarchiveObject("qualifier");
>        if (qualifier != null) {
>            // use the qualifier
>        }
> 
>        // get the date that was in session
>        LocalDate dateDebut = filtersArchive.unarchiveObject("dateDebut");
> 
>        // get array of EOs
>        NSArray<Machine> rapportMachines = 
> filtersArchive.unarchiveObject("rapportMachines");
>        ...
>    }
> }
> 
> 
> 
> 
> Utility class source

package com.kaviju.commons.model;

import com.webobjects.eocontrol.EOEditingContext;
import com.webobjects.eocontrol.EOGenericRecord;
import com.webobjects.eocontrol.EOGlobalID;
import com.webobjects.eocontrol.EOKeyValueArchiver;
import com.webobjects.eocontrol.EOKeyValueArchiving;
import com.webobjects.eocontrol.EOKeyValueUnarchiver;
import com.webobjects.foundation.NSArray;
import com.webobjects.foundation.NSKeyValueCoding;
import com.webobjects.foundation.NSMutableArray;

import er.extensions.foundation.ERXValueUtilities;

public class KAKeyValueArchive {
        static {
                EOKeyValueArchiving.Support.setSupportForClass(new 
KAKeyValueArchiverEoSupport(), EOGenericRecord.class);
        }

        private KAKeyValueArchiver archiver;
        
        public KAKeyValueArchive() {
                archiver = new KAKeyValueArchiver();
                archiver.setDelegate(new ArchiverDelegate());
        }
        
        public void archiveObject(Object object, String key) {
                object = object != null ? object : NSKeyValueCoding.NullValue;
                archiver.encodeObject(object, key);
        }
        
        public KAKeyValueUnarchiver 
unarchiverWithEditingContext(EOEditingContext ec) {
                return new KAKeyValueUnarchiver(this, ec);
        }
        
        // EOKeyValueArchiver n'encode pas les NSArray correctement...
        public static class KAKeyValueArchiver extends EOKeyValueArchiver {
                @SuppressWarnings({ "unchecked", "rawtypes" })
                @Override
                protected void _encodeArrayForKey(NSArray objects, String key) {
                        int count = objects.count();
                        if (count > 0) {
                                NSMutableArray<Object> array = new 
NSMutableArray<>(count);
                                for (int i = 0; i < count; i++) {
                                        KAKeyValueArchiver nestedCoder = new 
KAKeyValueArchiver();
                                        nestedCoder.setDelegate(delegate());

                                        Object object = 
objects.objectAtIndex(i);
                                        nestedCoder.encodeObject(object, 
"dictionary");
                                        
array.addObject(nestedCoder.dictionary().objectForKey("dictionary"));
                                } 
                                this._propertyList.setObjectForKey(array, key);
                        } else {
                                this._propertyList.setObjectForKey(objects, 
key);
                        } 
                }
        }
        
        public static class KAKeyValueUnarchiver {
                private KAKeyValueArchive archive;
                private EOKeyValueUnarchiver unarchiver;
                
                public KAKeyValueUnarchiver(KAKeyValueArchive archive) {
                        this.archive = archive;
                }

                public KAKeyValueUnarchiver(KAKeyValueArchive archive, 
EOEditingContext ec) {
                        this.archive = archive;
                        setEditingContext(ec);
                }

                public void setEditingContext(EOEditingContext ec) {
                        unarchiver = new 
EOKeyValueUnarchiver(archive.archiver.dictionary());
                        unarchiver.setDelegate(new UnarchiverDelegate(ec));
                }

                @SuppressWarnings({ "unchecked" })
                public <T extends Object> T unarchiveObject(String key) {
                        Object value = unarchiver.decodeObjectForKey(key);
                        if (ERXValueUtilities.isNull(value)) {
                                return null;
                        }
                        return (T)value;
                }
        }

        public static class KAKeyValueArchiverEoSupport extends 
EOKeyValueArchiving.Support {

                @Override
                public void encodeWithKeyValueArchiver(Object paramObject, 
EOKeyValueArchiver param1eoKeyValueArchiver) {
                        
param1eoKeyValueArchiver.encodeReferenceToObject(paramObject, "eo");            
        
                }

                @Override
                public Object 
decodeObjectWithKeyValueUnarchiver(EOKeyValueUnarchiver 
param1eoKeyValueUnarchiver) {
                        return 
param1eoKeyValueUnarchiver.decodeObjectReferenceForKey("eo");
                }
        }
        
        public static class ArchiverDelegate implements 
EOKeyValueArchiver.Delegate {

                @Override
                public Object referenceToEncodeForObject(EOKeyValueArchiver 
paramEOKeyValueArchiver, Object paramObject) {
                        if (paramObject instanceof EOGenericRecord) {
                                return 
((EOGenericRecord)paramObject).__globalID();
                        }
                        return paramObject;
                }
        }
        
        public static class UnarchiverDelegate implements 
EOKeyValueUnarchiver.Delegate {
                private final EOEditingContext ec;
                
                public UnarchiverDelegate(EOEditingContext ec) {
                        this.ec = ec;
                }

                @Override
                public Object unarchiverObjectForReference(EOKeyValueUnarchiver 
param1eoKeyValueUnarchiver, Object paramObject) {
                        if (paramObject instanceof EOGlobalID) {
                                return ec.faultForGlobalID((EOGlobalID) 
paramObject, ec);
                        }
                        return paramObject;
                }
        }
}

 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list      (Webobjects-dev@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to