Dynamic data sequence. Delete element. Java

25 posts / 0 new
Last post
Offline
Last seen: 2 years 1 month ago
Joined: 11/08/2014
Posts: 19
Dynamic data sequence. Delete element. Java

Hi

I've created a treetable editor for DDS topics that uses dynamic data as its focal point.

One edited, the topic is output as XML for storage and can be re-read back into dynamic data for further editing within the treetable or for publishing.

I can add elements to both complex and simple sequences but I can't find a way to delete them.

I've tried clear_all_members, but this seems to do nothing, delete() just screws things up.

I'm using the Java API.

Any examples?

Thanks

John

 

Organization:
Offline
Last seen: 2 years 1 month ago
Joined: 11/08/2014
Posts: 19

My editor is now complete, except for sequence element deletion.

It's not a showstopper as I can delete by editing the output XML and reading it back in, but it's just not right.

Can someone tell me if it's possible to delete an element, connect the two adjacent dynamic data elements and modify the count of the parent?

Thanks

John

 

 

rip
rip's picture
Offline
Last seen: 1 week 4 days ago
Joined: 04/06/2012
Posts: 318

{third times the charm, the first answer was wrong, the second answer was lost when my laptop crashed}

Dynamic Data elements are views on an octet sequence.  The reflection built into the DynamicData object allows it to determine where it is looking in the buffer and present to you, based on knowledge of the Type, what the data is. 

What it isn't, is a(n abstract) sequence of pojo objects. 

We don't provide a conversion method to go back and forth between a pojo (for example, one generated by rtiddsgen) and DynamicData.  If this were available, you could convert the DynamicData into a pojo, use the java abstract sequence api remove() call on the element to be removed, and then convert it back. 

Autogenerating a converter based on IDL is achievable, now that we have rtiddsgen2 to play with.  But I don't think that this is the right use case, as the use of DynamicData in tools presupposes that you don't have access to the IDL that defined the Type, in the first place.

Another option is to recursively copy one DynamicData object into another, skipping the to-be-deleted object, taking into account the reduced number of objects in the sequence.  That might be faster than dumping XML, editing it and then loading it back in.

A third option would be to instead of generating XML, instead convert the DynamicData into a W3C DOM object and manipulate that, then convert back into DynamicData. 

All of these options require that the original octet buffer be converted into some other form first, sorry, except for the DD -> DD copy, which should be the fastest (and probably easiest to implement, since it requires knowledge of only one art form, that being DynamicData).

Now, hopefully this one successfully posts.

Offline
Last seen: 2 years 1 month ago
Joined: 11/08/2014
Posts: 19

Hi rip

Successfully posted and thanks.

I didn't think of the copy thing.  This will just be a re-use of the code I've already written for changing data content/adding to sequences.

Excellent idea.

John

rip
rip's picture
Offline
Last seen: 1 week 4 days ago
Joined: 04/06/2012
Posts: 318

You're welcome!

Let us know how you get on.

rip

Offline
Last seen: 2 years 1 month ago
Joined: 11/08/2014
Posts: 19

This works up to a point.

I can delete all but the last element in a sequence as follows...

i is the index of the element I am attempting to delete.

                int count = dynamicData.get_member_count();
                dynamicDataCopy.clear_all_members();
                  
                int k=0;
                for(int j=0;j<count;j++)
                {
                   if(publisher.isComplex(info.member_kind))
                   {
                        newDynamicData = new DynamicData(null, DynamicData.PROPERTY_DEFAULT);                       
                        dynamicData.get_complex_member(newDynamicData, null,j+1);
                        if(j!=i)
                        {
                            dynamicDataCopy.set_complex_member( null,k+1,newDynamicData);
                            k++;
                        }                        
                   }
                   else
                   {
                        dynamicData.get_member_info_by_index(info,j);
                        String data = publisher.getPrimitiveData(dynamicData, info);
                        if(j!=i)
                        {
                            dynamicData.get_member_info_by_index(info,k);
                            publisher.setPrimitiveData(dynamicDataCopy, info, data);
                            k++;
                        }
                   }
                }
 
At this point I've recursed into the sequence with dynamicData and its copy. 
I clear all members within the copy (the copy get_member_count returns zero) and use set_complex or set (primitive) to copy in all but the one I want deleted.
This works until I come to delete the final element. It seems that the element count in the copy is only changed by the 'set' operations.
Although clear_members seems to modify the element count it remains at one once I exit the routine and re-recurse to output XML or update my treetable.
 
Any suggestions?
 
In the meantime I'll keep hitting the keys in the hope I find something. If I do I'l report back.
 
Thanks
 
J
 
 
Offline
Last seen: 2 years 1 month ago
Joined: 11/08/2014
Posts: 19

Couldn't figure out how to do this so my code's been released with a pop-up if the user attempts to delete the final sequence element :-(

As I said in an earlier post, they can always edit the XML version of the edited data and read it back in (which is what the pop-up says). 

rip
rip's picture
Offline
Last seen: 1 week 4 days ago
Joined: 04/06/2012
Posts: 318

I'm not quite sure I get the setup.  The edge cases I see are

1) Delete the first element of N|N>1 element sequence

2) Delete the last element of an N|N>1 element sequence

3) Delete a non-first, non-last element of an N|N > 2 element sequence

4) Delete the single (sole) element in a 1 element sequence

your code works for which cases, and is failing for which cases?



Offline
Last seen: 2 years 1 month ago
Joined: 11/08/2014
Posts: 19

Hi rip

It's the last one (4) . It seems that the only way to change the count is using 'set' or 'set_complex'. 

If I have a two element sequence and I want to delete either of them then I just 'set' the blanked (clear_all_members) copy of my dynamic data to the value I want to keep and the count has changed to one the next time I use it.

If I have a one element sequence and I want to delete its sole member then there's no 'set' to do and you might assume that the blanked copy would have its count set to zero (as it reports within the code that is doing the modification). However when I use the copy (which in all other cases correctly represents the modified sequence count), the count remains at one, not zero as expected.

J

rip
rip's picture
Offline
Last seen: 1 week 4 days ago
Joined: 04/06/2012
Posts: 318

If you are deleting the sole element in a one-element list... wouldn't that be also expressed as 'I don't need this sequence at all'?

What happens if instead you simply don't set the dynamicDataCopy sequence complex member at all?   I'm trying to remember if this what the DynamicData reflection expects.

Shot in the dark.

Offline
Last seen: 2 years 1 month ago
Joined: 11/08/2014
Posts: 19

Hi rip

We're running with what we've got at the moment and I'll be making further mods when I get feedback.

Our typedefs include empty sequences to be filled (or not) by the user so the empty sequence has to be visible in the treetable editor.

You wrote:

What happens if instead you simply don't set the dynamicDataCopy sequence complex member at all? 

Well that's the problem. I clear it and don't set it and it reports its count as zero within the code doing the modifying, however when I revisit it it reports its count as one and still contains the last set member.

J

rip
rip's picture
Offline
Last seen: 1 week 4 days ago
Joined: 04/06/2012
Posts: 318

See, now that's just weird.

Any chance you can supply a reproducer to support@rti.com?  If you don't have a support account, you can send it to me directly and I'll look at it.  My email is com.rti@rip (a human should figure that out :) )

 

Offline
Last seen: 2 years 1 month ago
Joined: 11/08/2014
Posts: 19

rip

We do have a support account, but this is for a project which I'm not part of. Also, this is complicated and I don't reliish the thought of having to explain it to both the project people and again to your support guys. You have a head start, so if you don't mind....

I can post this to you if you wish, but transferring anything from my development system to the company email is well fiddly. 

The code below does not exhibit exactly the same behaviour as the problems I've seen, but it amounts to the same thing, the differences may be due to the differing type codes. 

 
package dynamicdatatest;
 
import com.rti.dds.dynamicdata.DynamicData;
import com.rti.dds.typecode.StructMember;
import com.rti.dds.typecode.TypeCode;
import com.rti.dds.typecode.TypeCodeFactory;
 
 
public class DynamicDataTest 
{
    public static void main(String[] args) 
    {
        
        //Create a type of sequence of TC_LONG (int) of max 2 elements
        TypeCode intSeqTC = TypeCodeFactory.TheTypeCodeFactory.create_sequence_tc(2, TypeCode.TC_LONG);
        
        //Create a structure containing one of the above type
        StructMember[] sms=null;
        sms = new StructMember[1];
        sms[0] = new StructMember("seq",false,TypeCode.NOT_BITFIELD,false,intSeqTC);
         
        //Create a type of the above structure
        TypeCode complexTC = TypeCodeFactory.TheTypeCodeFactory.create_struct_tc("intSeq", sms);
        
        //Dynamic data for the above complex type
        DynamicData complexDynamicData = new DynamicData(complexTC,DynamicData.PROPERTY_DEFAULT);
        DynamicData complexDynamicDataCopy = new DynamicData(complexTC,DynamicData.PROPERTY_DEFAULT);
       
        //Dynamic data for the for the complex type's content
        DynamicData dynamicData = new DynamicData(intSeqTC,DynamicData.PROPERTY_DEFAULT);
        DynamicData dynamicDataCopy = new DynamicData(intSeqTC,DynamicData.PROPERTY_DEFAULT);
 
        int count = dynamicData.get_member_count();
        
        //Set two successive elements in the empty sequence to 10 and 20
        dynamicData.set_int(null, 1, 10);
        dynamicData.set_int(null, 2, 20);
 
        //Set the sequence on the complex member
        complexDynamicData.set_complex_member(null, 1, dynamicData);
 
        dynamicData.clear_all_members();
        
        //Get the sequence from the complex member
        complexDynamicData.get_complex_member(dynamicData, null, 1);
        complexDynamicDataCopy.get_complex_member(dynamicDataCopy, null, 1);
 
        int val;
        //Returns 2 as expected
        count = dynamicData.get_member_count();
        //Returns 0 as expected
        count = dynamicDataCopy.get_member_count();
        //These return zero.
        //They haven't been set and 3 and 4 are beyond the sequence bounds - should these raise an exception?  
        val = dynamicDataCopy.get_int(null, 1);
        val = dynamicDataCopy.get_int(null, 2);
        val = dynamicDataCopy.get_int(null, 3);
        val = dynamicDataCopy.get_int(null, 4);
 
        val = dynamicData.get_int(null, 1);
        //Set the first element of the copy to be the same as the original
        dynamicDataCopy.set_int(null, 1, val);
 
        val = dynamicData.get_int(null, 2);
        //Set the second element of the copy to be the same as the original
        dynamicDataCopy.set_int(null, 2, val);
        
        complexDynamicData.set_complex_member(null, 1, dynamicData);
        complexDynamicDataCopy.set_complex_member(null, 1, dynamicDataCopy);
 
        complexDynamicData.get_complex_member(dynamicData, null, 1);
        complexDynamicDataCopy.get_complex_member(dynamicDataCopy, null, 1);
 
        //Count for both as expected - 2
        count = dynamicData.get_member_count();
        count = dynamicDataCopy.get_member_count();
        
        //Values of copy as expected
        val = dynamicDataCopy.get_int(null, 1);
        val = dynamicDataCopy.get_int(null, 2);
 
        //Clear the copy
        dynamicDataCopy.clear_all_members();
        //Count zero as expected
        count = dynamicDataCopy.get_member_count();
        
        //Set the first member of the copy to be the same as the second member of the original 
        val = dynamicData.get_int(null, 2);
        dynamicDataCopy.set_int(null, 1, val);
 
        //Count 1 as expected
        count = dynamicDataCopy.get_member_count();
 
        complexDynamicDataCopy.set_complex_member(null, 1, dynamicDataCopy);
 
        dynamicDataCopy.clear_all_members();
        
        complexDynamicDataCopy.get_complex_member(dynamicDataCopy, null, 1);
        //count one as expected
        count = dynamicDataCopy.get_member_count();
        val = 0;
        //Value 20 as expected
        val = dynamicDataCopy.get_int(null, 1);
        //Again, returns zero, but as count is only one shouldn't this raise an exception?
        val = dynamicDataCopy.get_int(null, 2);
        
        dynamicDataCopy.clear_all_members();
        //count is zero
        count = dynamicDataCopy.get_member_count();
        
        //Set the cleared Dynamic Data sequence on to the complex member
        complexDynamicDataCopy.set_complex_member(null, 1, dynamicDataCopy);
        
        //Get it back
        complexDynamicDataCopy.get_complex_member(dynamicDataCopy, null, 1);
        
        //This is where it goes wrong
        //Count now equals 2 
        count = dynamicDataCopy.get_member_count();
        val = 0;
        //Values back to the original 10 and 20
        val = dynamicDataCopy.get_int(null, 1);
        val = dynamicDataCopy.get_int(null, 2);
  
    }
}
 
rip
rip's picture
Offline
Last seen: 1 week 4 days ago
Joined: 04/06/2012
Posts: 318

You have a comment: 

  //They haven't been set and 3 and 4 are beyond the sequence bounds - should these raise an exception? 

Yep:

Exception in thread "main" com.rti.dds.infrastructure.RETCODE_NO_DATA
    at com.rti.dds.util.Utilities.rethrow(Utilities.java:92)
    at com.rti.dds.infrastructure.RETCODE_ERROR.check_return_codeI(RETCODE_ERROR.java:142)
    at com.rti.dds.dynamicdata.DynamicData.get_int(DynamicData.java:464)
    at DynamicDataTest.main(DynamicDataTest.java:53)
DDS_DynamicData_get_long:!get_long

(disregard the 'at DynamicDataTest.main(DynamicDataTest.java:53' line number.  I'm adding commentary to the file so that number no longer has shifted some).

If that is different from what you are getting, that's problematic.  What platform are you on?

(Same as ''//Again, returns zero, but as count is only one shouldn't this raise an exception?'', it does on my system)

Now, for 'because, reasons'.

Try this methodolgy.  Instead of trying to get/set the individual items, get the sequence, manipulate the sequence, set the sequence.  Note this rework uses bind/unbind and typecode peeking to determine that I need to use get_int_seq/set_int_seq...even though the code sets it up that way earlier.  Because, reasons.

import com.rti.dds.dynamicdata.DynamicData;
import com.rti.dds.infrastructure.*;
import com.rti.dds.typecode.*;
 
public class DynamicDataTest 
{
    public static void main(String[] args) 
    {
        
        //Create a type of sequence of TC_LONG (int) of max 2 elements
        TypeCode intSeqTC = TypeCodeFactory.TheTypeCodeFactory.create_sequence_tc(2, TypeCode.TC_LONG);
        // typedef sequence<long, 2> intSeqTC;
        
        //Create a structure containing one of the above type
        StructMember[] sms=null;
        sms = new StructMember[1];
        sms[0] = new StructMember("seq",false,TypeCode.NOT_BITFIELD,false,intSeqTC);
         
        //Create a type of the above structure
        TypeCode complexTC = TypeCodeFactory.TheTypeCodeFactory.create_struct_tc("intSeq", sms);
        
        //Dynamic data for the above complex type
        DynamicData complexDynamicData = new DynamicData(complexTC,DynamicData.PROPERTY_DEFAULT);
       
        //Dynamic data for the complex type's content
        DynamicData dynamicDataOfSeq = new DynamicData(intSeqTC,DynamicData.PROPERTY_DEFAULT);
        DynamicData scratchDynamicData = new DynamicData();
        
        int count;
        count = dynamicDataOfSeq.get_member_count();
        
        //Set two successive elements in the empty sequence to 10 and 20
        dynamicDataOfSeq.set_int(null, 1, 10);
        dynamicDataOfSeq.set_int(null, 2, 20);
        int val;
        val = dynamicDataOfSeq.get_int(null, 1);
 
        //Set the sequence on the complex member
        complexDynamicData.set_complex_member(null, 1, dynamicDataOfSeq);
        
        //Get the sequence from the complex member via a previously unused DynamicData Object
	// note that the object has not been configured with a type!
        complexDynamicData.bind_complex_member(scratchDynamicData, null, 1);
        count = scratchDynamicData.get_member_count(); // 2
        val = scratchDynamicData.get_int(null, 1);     // 10
        val = scratchDynamicData.get_int(null, 2);     // 20
        complexDynamicData.unbind_complex_member(scratchDynamicData);

        // Drop the item in slot 1, in favor of slot 2
        TypeCode tc = complexDynamicData.get_member_type(null, 1);
        try {
            if (tc.kind() == TCKind.TK_SEQUENCE) {
                if (tc.content_type() == TypeCode.TC_LONG) {
                    IntSeq intSeq = new IntSeq();
                    complexDynamicData.get_int_seq(intSeq, null, 1);
                    count = intSeq.size(); // 2
		    // note these are now 0-based indices
                    intSeq.set(0, intSeq.get(1));     // 20
                    intSeq.remove(1);
                    complexDynamicData.set_int_seq(null, 1, intSeq);
                }
            }
        } catch (BadKind bk) {
            System.out.println("BadKind");
        }
        
        complexDynamicData.bind_complex_member(scratchDynamicData, null, 1);
        count = scratchDynamicData.get_member_count(); // 1
        val = scratchDynamicData.get_int(null, 1);
        try {
            val = scratchDynamicData.get_int(null, 2);
        } catch (Exception ee) {
            val = -1;
        }  
        complexDynamicData.unbind_complex_member(scratchDynamicData);
    }
}

To delete everything in the sequence, I would simply

    IntSeq intSeq = new IntSeq(); 
    complexDynamicData.set_int_seq(null, 1, intSeq);

 

Offline
Last seen: 2 years 1 month ago
Joined: 11/08/2014
Posts: 19

Thanks rip

I've got some other stuff to do which is pressing, but I will get back to this this week and tell you how I got on.

I'm using Netbeans 7.3.1 on Windows 7 Enterprise. I get no exception message, but on closer inspection I do get the last line...

DDS_DynamicData_get_long:!get_long

which I didn't see in amongst the debug dialog.

John

Offline
Last seen: 2 years 1 month ago
Joined: 11/08/2014
Posts: 19

Hi rip

 

Just got back to this and I realise that although the example I gave does illustrate the problem, I shouldn't have chosen a primitive type as the sequence member. The majority of my sequences are sequences of complex type and there doesn't appear to be an equivalent complex solution to set_int_seq (null).  Sorry, I should have thought of that.

 

So I still don't know how to clear the last member out of a sequence of complex types....

J

 

 

Offline
Last seen: 2 years 1 month ago
Joined: 11/08/2014
Posts: 19

Oh.  Hold on...

Offline
Last seen: 2 years 1 month ago
Joined: 11/08/2014
Posts: 19

No that didn't work. I've run out of ideas now.

I won't be back until the 5th Jan 2015. Have a good christmas.

J

Offline
Last seen: 2 years 1 month ago
Joined: 11/08/2014
Posts: 19

Well, Christmas provided me with no insight into this problem, so I'm stuck in the same position as I was when I wrote #16.

Any further thoughts?

 

rip
rip's picture
Offline
Last seen: 1 week 4 days ago
Joined: 04/06/2012
Posts: 318

Hiya,

Yeah, the insight is "you need to write the entire app framework to wrap the 10 or so lines of code that demonstrates the algorithm that you want to show" :)

I've got the framework which I assembled over the holidays (family notwithstanding), I will get the rest of it this week (no more family around).

rip
rip's picture
Offline
Last seen: 1 week 4 days ago
Joined: 04/06/2012
Posts: 318

So the below is the "quick" algorithm.  It assumes that there is an element in the sequence that you want to drop.  The copy uses the fast get_/set_ complex member methods to copy the existing into a buffer, and then copy the buffer into the target sequence.  It correctly handles 

01(2)3 -> 013
(0)13 -> 13
1(3) -> 1
(1)3 -> 3
(3) -> 

but fails on

1234 -> 1234

go figure.  It's something internal:  DDS_DynamicData_unbind_complex_member:internal error 1 trying to to stream

If I know that the element I want to delete is not in the current sequence (either in the sequence or within a child of the sequence) I would do the get_/set_ at the higher level, ie get(seq), set(seq) rather than for_elements_in_seq { get(ele), set(ele) } and hopefully bypass that problem.

    System.out.print("is a TK_SEQUENCE<");
    TypeCode outertc = src.get_member_type(null, memberId);
    TypeCode tc = outertc.content_type();

    // do we want to remove one of these elements?
    boolean check = (memberName.compareTo(field) == 0);

    // src is the container holder, so get the container
    DynamicData srcSeq = new DynamicData(null, DynamicData.PROPERTY_DEFAULT);
    src.bind_complex_member(srcSeq, memberName, DynamicData.MEMBER_ID_UNSPECIFIED);
    DynamicDataInfo eInfo = new DynamicDataInfo();
    srcSeq.get_info(eInfo);
    int count = eInfo.member_count;
    System.out.print(tc.name() + ", " + count + "> \n");
    // Element (innards) ndx (0) memberId (1) is a TK_SEQUENCE<InnerStruct, 4> 

    // tgt is the container holder, so get the container
    DynamicData tgtSeq = new DynamicData(null, DynamicData.PROPERTY_DEFAULT);
    tgt.bind_complex_member(tgtSeq, memberName, DynamicData.MEMBER_ID_UNSPECIFIED);
                
    DynamicData dde = new DynamicData(tc, DynamicData.PROPERTY_DEFAULT);
    int p = 0; // memberId base 1 so will ++p on use
    for (int elm = 1; elm <= count; elm++) 
    {
        if (check && (elm == (toDrop + 1))) 
        { 
            System.out.println("elm | " + elm + " (dropped)");
            continue; 
        }
        srcSeq.get_complex_member(dde, null, elm);
        tgtSeq.set_complex_member(null, ++p, dde);
        System.out.println("elm > " + elm + " into " + p + " (ok)");
    }
    src.unbind_complex_member(srcSeq);
    tgt.unbind_complex_member(tgtSeq);

The framework recursively enters a function which decides what to do based on member_info kind and TCKind, until it hits a sequence or an array.  This is the IDL I used:

struct InnerStruct {
    string<8> aString;
    long aLong;
    sequence<long, 8> aLongSeq;
};

struct MiddleStruct {
    sequence<InnerStruct, 8> innards;
};

struct Outer {
    long primitive;
    MiddleStruct thorax;
    InnerStruct anArray[8];
};

The framework is not fully recursive -- it does not try to descend into sequence or array elements.  It will recurse into structs and copy primitives and non-sequence/array elements, recursively, but once it hits a sequence or array that's as far as it will go on that branch (instance.thorax.innards are processed as atomic elements). 

Obligatory trailer:  DynamicData is going to change with a future release (in line with the XTypes standard), the above is using the 5.1.0 and prior API.

Offline
Last seen: 2 years 1 month ago
Joined: 11/08/2014
Posts: 19

Hi rip

Thanks. 

I've got some less interesting stuff I have to deal with, so it may be next week before I can unpick this.

I'll get back as soon as I can.

John

Offline
Last seen: 2 years 1 month ago
Joined: 11/08/2014
Posts: 19

rip

Struggling get this to work with my code, I have nested sequences (not my choice) so full recursion is neccessary.

As previously dicussed insertion and deletion of elements works perfectly using the copy method you suggested.  Presumably the clear_all_members() should do as it suggests on a bound member and an empty sequence should result once it is unbound. The fact that it doesn't indicates a bug (?).

The next thing I tried was to identify when my deleteElement() code entered with a count of one. In this case no deletion was attempted and, on exit, I created a new, empty, sequence header which I then set at that level. This always worked, but unfortunately it also took out adjacent sequences leaving only the headers.  This behaviour was inconsistent and I'm guessing may be another bug.

As the API is to change I guess there's no incentive to fix the clear_all_member() thing so I'll carry on with what I've got (if the user wants to delete the last element in a sequence, they'll have to edit the XML output and read it back in).

Thanks again for all your help with this.

John 

rip
rip's picture
Offline
Last seen: 1 week 4 days ago
Joined: 04/06/2012
Posts: 318

Hi John,

Yeah, sounds like a lot of proprietary stuff, alas.   I would have to recreate your entire application internals, including recursive descent, and ...

On the other hand, I'm available for contract work at the moment.  I live in Edinburgh, how close is that to you :D .

clear_all_members will "Clear the contents of all data members of this object, including key members.

What I'm wondering is -- given the way DynamicData is structured, a sequence is internally:

[A] DynamicData Object (TK_SEQUENCE)
[B] -> DynamicData Object (the sequence values, as an anonymous construct)
[C] -> -> DynamicData Object (a value in the sequence, a TK_STRUCT)

(read that as given [A], you bind a DynamidData object to the TK_SEQUENCE, and now you have a sequence.  You bind a DynamicData object then to each of the values in the sequence, one at a time)

I believe clear_all_members will work only on [C], ie it will clear a TK_STRUCT's member values to 0, 0.0, '', NULL, but I'm unsure what it will do with [B], and I'm guessing it will have no effect at all on [A].  You could call clear_all_members() on the TK_SEQUENCE's parent, but that would blow away all the values from the other fields in that struct.

I might be able to help you optimize the XML handling, though.  Does the java tree class have an "export XML" function? or are you using a W3C DOM object? There are tools that can generate java classes that will handle either the DOM or the raw XML (by converting it into a DOM), process it to remove the unwanted nodes, then hand it back (as DOM or as new serialized XML).  The one I'm thinking of is MapForce (from Altova, they also do XMLSpy). 

but yeah, maybe we've beaten this one to death.

rip

Offline
Last seen: 2 years 1 month ago
Joined: 11/08/2014
Posts: 19

rip

I have two DynamicData objects representing sequences of TK_STRUCT, a source and a target (your [A]). To remove any single element from the sequence I have to clear_all_members() on the target then copy all but the element I want to omit into the (cleared)target using set_complex_member.

If I don't clear_all_members() before the copy then the behaviour is inconsistent varying from no change at all to all sequence elements being removed.  This makes no sense and suggests something fundamentally bust in the internals.

Having picked around the edges of the initial problem trying to find a workaround I've uncovered other mysterious behaviour.  Frankly I think I'm lucky to have produced code which is apparently reliable as far as it goes.

Thank you for your kind offer of contract work :-)  but Bristol may be too far and as I said earlier, this isn't a showstopper, the code is in use and working and it may be that nobody ever wants to delete the last element in a sequence, if they do then the export/import code (W3C DOM) I wrote will allow the manual deletion of the last element.

Cheers

John