Skip to main content

A few design questions about a library

No replies
i30817
Offline
Joined: 2006-05-02

Hi. I'm doing a library to encapsulate a compressed archive type (either rar, zip or tar.bz right now), motivated by the release of the junrar library.
The library will be read only, but i want to have some functionalities of selection, filtering and ordering.

I'm going for a fluent interface where for example this code would be legal:

<br />
ContentExtractor content;<br />
try{<br />
content = Compressed.extractFrom("test.rar").<br />
selectBySuffix(".rtf", false).<br />
filterByArchiveDateInequality(LARGER_THAN, someDate).<br />
endSelection().orderByAscending(DATE).extract();<br />
InputStream i;<br />
for(Contents c : content){<br />
try{<br />
i = c.getInputStream(); //lazy<br />
Date modDate = c.getModificationDate();<br />
} finally{<br />
close(i);<br />
}<br />
}<br />
}finally{<br />
close(content);<br />
}<br />

My questions come from the interaction of the selectByXXX() methods and the filterBy.
A concatenation of selectBy() would work like OR predicates, and of filterBy() as AND. Whenever a filterMethod is called selectBy() methods can't be called again - is this a good idea? I did it to make this easy in the autocomplete, and the fact that a filter() command without a preceding select() is a NOP. But is the ability to make a filter of like:
condiction().filter().condiction2() - ie: get all that have a property, filter them by a rule then add others. Possible with the current form? Desirable?
condiction().condiction2().filter() .... filter20()

Also due to the vagaries of the interaction between the file formats, selection and filtering i'm having a small problem:
There is the possibility in zip at least that supports multiple formats (tar etc) that some fields are missing. Now with the modification date, the only way is returning null, and with the double values (filesize, etc) i thought of using NaN as a universal notEqual number, that disallows null pointer exceptions.
However i find that for the most intuitive usage i need a universal object value ie null.
you see the Inequalities above are defined as

<br />
public enum Inequality {</p>
<p>    LARGER_THAN {<br />
        public boolean test(Comparable c1, Comparable c2) {<br />
            return c1 != null && c2 != null && c1.compareTo(c2) > 0;<br />
        }<br />
    }, LARGER_THAN_OR_EQUAL {<br />
        public boolean test(Comparable c1, Comparable c2) {<br />
            return c1 != null && c2 != null && c1.compareTo(c2) >= 0;<br />
        }<br />
    }, LESSER_THAN {<br />
        public boolean test(Comparable c1, Comparable c2) {<br />
            return c1 != null && c2 != null && c1.compareTo(c2) < 0;<br />
        }<br />
    }, LESSER_THAN_OR_EQUAL {<br />
        public boolean test(Comparable c1, Comparable c2) {<br />
            return c1 != null && c2 != null && c1.compareTo(c2) <= 0;<br />
        }<br />
    }, EQUAL {<br />
        public boolean test(Comparable c1, Comparable c2) {<br />
            return c1 != null && c2 != null && c1.compareTo(c2) == 0;<br />
        }<br />
    };</p>
<p>    public abstract boolean test(Comparable c1, Comparable c2);<br />
}<br />

This was done so that they could be used by any value, even if the format is not supporting it. However as you can tell what selection and filtering when the format does not allow a certain value is what is interesting.

Selecting using this function with a null or NaN means that nothing would be selected.
I believe this is the intuitive behavior, if we can't know what to select we select nothing.

On the other hand filtering with (done with the negatory of test() ) would mean that if a value is not supported EVERYTHING would be filtered. On the other hand if null would be a universal accept value, ie:

return c1 == null || c2 == null || c1.compareTo(c2) == 0;
Then everything would be selected and nothing filtered in the case where the value is not known.

I believe the best solution is two methods
return c1 != null && c2 != null && c1.compareTo(c2) == 0;
return c1 == null || c2 == null || c1.compareTo(c2) == 0;
for selection or filtering with null values to be a identity operation. Also drop the double.NaN and use objects for everything.
However this has the (already existed for the date at least) additional burden, of the client needing to test
if(XXX != null) for each Content that can be null. Any ideas to avoid that?

Message was edited by: i30817

Message was edited by: i30817

Message was edited by: i30817