On 13 Dec 2006, at 20:40, Joshua Hansen wrote:
Hi Geert,
Since it could be a while before I'm able to make a significant
code contribution, I'll reply to what can be done right away. :)
Even a small one is very welcomed. For example, adding the
addTransformer capability with javadocs and tests relieves the
See the rest inline...
Shalom,
Josh
--
Joshua Hansen
Up Bear Enterprises
(541) 760-7685
Geert Bevin wrote:
Hi Joshua,
I think the heart of my question is really a question about the
performance of java.awt.Image. :) If the performance (speed,
memory) of java.awt.Image is poor, then that creates a bottleneck
in transforming images and loading them (and their properties)
into the database. So, abstracting to allow a drop-in
representation or library seems logical and an additional
advantage. :) However, "don't guess, measure", eh? :)
java.awt.Image is the most basic of Image classes possible, other
image classes extend this one. So it should be totally appropriate
as the common data vehicle for image handling and transformation.
My specific task is that I'm building a photo gallery app, and I
want to generate 3 (maybe more) versions of an uploaded file.
Since there could potentially be a lot of files uploaded, it
would be nice to have "low" memory and CPU usage.
Well, the thing is that if you want to resize, convert or
transform an image, you need to load it into memory at some point
in time. If you just want to store the image, you can stream it
straight to the content manager framework using the RAW target
mime type.
Image transform-wise, I've run into a situation (twice now) where
I set a 'width' or 'height' value, but the orientation of some of
the images is opposite which causes it to be scaled incorrectly
(i.e. both 1200x1600 images and 1600x1200 images should use the
same scaling ratio but simply setting a width or height doesn't
give this result), so I created a transformer which uses
attributes 'short-edge-length' and 'long-edge-length', which does
just what I want. Yay! :)
I wonder if this class that you added to the wiki should be
included into RIFE and use a content attribute to make the CMF to
adopt it. What do you think?
I think it's a good complement to the 'width' and 'height' setters,
so yeah, it would be a useful item to have in the CMF.
Before I go on and talk about RIFE, I'll say that I'm still a
little fuzzy on the workflow for how an image (file) goes from
the temporary upload directory through the transformers, validator
(s) and into the database.
Does this answer your question?
http://rifers.org/wiki/display/RIFE/Content+management
+framework#Contentmanagementframework-2
That document is really helpful, and I spent some time looking at
it (and will be spending more), but what I was referring to is how
some of the items get instantiated, then get referenced, and
finally get invoked. That document shows what happens ultimately,
but the actual sequence of class instantiations, references, and
then method calls is not as straight-forward. I think it will just
come from spending more time with it. :) You are also making heavy
use of Java 5.0 features too (which is great), which I'm still
coming up to speed on, so that's something else for me.
MimeType: Yes, making the constructor public would allow
additional MimeTypes. Would it also allow overriding the static
MimeTypes?
It should. Can you please add a Jira issue for this?
Done. Suggestion: Add a 'cmf' component to Jira. I filed it in
Unknown, and against 1.4 (since that's what's I'm using), and
marked it bite-size with the assumption that the only change is to
make the constructor protected or public. I'll leave it to you to
change make any relevant adjustments.
Good thing or bad thing since they would need to be changed
before DatabaseImageStore is instantiated? Would a Participant
be able to handle this, like the ResourceFinder mechanism?
Yes.
Cool.
DatabaseImageStore: The only thing here that is obviously image
specific is getContentForHtml(), and that's not image type
specific, so pulling the list of MimeTypes from something that
could be overridden seems possible, though I don't have any quick
and elegant ideas about how to do it either. BTW -- it seems
weird to me that getContentForHtml() is in this class. I suspect
I keep think of 'Store' as a verb when it's really a noun. :)
It is indeed a noun in this case ;-)
Other notes, and ideas...
In looking at ImageFormatter, the scaling feature (setting the
width/height) seems like it should really be extracted as a
separate content transformer. Conversion from various formats to
jpg should also be considered transforms (a single 'jumbo'
converter transformer could be used). This leaves the storage
mechanism as a validator ("Is what I'm getting an actual jpeg?")
and property extractor (width, height, whatever you like).
(Maybe property extractor should be considered a type of
transformer too? But, leave that question for later.)
These would indeed be good refactorings, something that should be
added then too is some way of registering multiple transformers
and to be able to specify their order. Feel free to propose a
approach for this. You seem to have a good chain of thoughts going
on here with (what looks like) a very distinct goal. This is a
perfect opportunity to contribute to the project!
I think this approach has a couple advantages. The conversion
from arbitrary formats becomes explicit which allows the user the
option to reject non-jpeg files (such as a case where conversion
could introduce artifacts and so you want to enforce/provide a
strict garbage-in-garbage-out behavior).
True, though one thing to consider is that the CMF should somehow
know which transformers to use based on the content attributes
that are provided. Maybe we should just iterate through all the
active transformers and each one decides if the transformations
need to be performed or not.
See below...
Another aspect is that it allows for lightweight analysis tools.
A shortcut validator (again, this could be a decision by the
user) could potentially just analyze the header and extract
properties from it which makes it very low impact on cpu and memory.
Interesting idea, indeed.
Maybe a convenient addition to the ConstrainedProperty api would
be to support multiple transformers. But, it isn't it's required
to have this, since a single custom transformer can be written
which just calls each of the additional desired transformers.
See, we're on the same page ;-)
Haha! :) I think the ConstrainedProperty API could be modified to
have an 'addTransformer(ContentTransformer)' method. This would be
a list of transformers, ordered by the call to addTransformer().
Example:
[in the MetaData class]
addConstraint(new ConstrainedProperty("imageMedium")
.notNull(true)
.file(true)
.editable(false)
.mimeType(MimeType.IMAGE_JPEG)
.contentAttribute("long-edge-length", 240)
.addTransformer(new PhotoScalingImageTransformer())
.addTransformer(new GreyScaleTransformer()))
);
This would result in 2 transformers being added to a list of
transformers to be executed for the 'imageMedium' property. They
would be executed in order, and each determine their activity based
on the provided attributes. The example above could represent a
flow which then scales the image by the longest edge, then converts
the scaled image to greyscale.
The existing ConstrainedProperty.transformer() method could be
modified to call the addTransformer() method, making the whole
thing backwards compatible.
As I think about it, teasing out the image conversion (from non-jpg
to jpg) will be more difficult, so, I'm just leaving it as is for
this discussion. :)
Sorry I don't have more constructive/concrete suggestions. I'll
keep thinking about it. The more I work w/ the framework, the
more I understand what it's doing and intent. :)
Cool :-)
I'll take a look into the RAW type again. I got stuck with file
uploads and mime-types when I first plunged into RIFE, and I've
learned a lot since then. Heck, I've learned a lot since 2
nights ago. :)
At any rate, I think adding MimeTypes would be a big advantage.
There are a lot of MimeTypes out there, and being able to publish
and download additional handlers would be awesome. Now that I
think about it, maybe the whole CMF system should really be
constructed in terms of pluggable MimeType handlers, then provide
some default implementations for the currently supported types.
Again, I agree that this should be investigated. When I created
the current limited set of enum mime-types, I did realize that it
was not flexible enough and that should would probably have to be
changed and refactored later. Seems this time has come :-)
Thanks again for an awesome framework! :)
Thanks :-) Please consider contributing code that reflects your
ideas, so that RIFE becomes even better.
I'm starting to plan on it, particularly since I'm getting further
into it and am seeing some opportunities for contribution! :)
Shalom,
Josh
Take care,
Geert
Shalom,
Josh
Geert Bevin wrote:
Hi Joshua,
currently there is no extension mechanism for this, but I'm
willing to look into any proposals since this rigidness has
always troubled me. With the enum mechanism that we use in RIFE,
you can add any other MimeType but the constructor is currently
too closed down, maybe it should just be made public. This means
that you would be able to add new MimeTypes.
One thing that you have to realize though, is that MimeType
entries specify how they they are validated and formatted, they
don't however indicate where they need to be stored. This is a
tricky thing to solve since the content storage back-ends are
abstracted away and currently detect directly on the MimeType
enum elements (they provide a collection of MimeTypes that
they're able to handle). When you add your custom MimeTypes,
those storage backe-end wouldn't be able to handle them though.
This is sadly currently hardcoded in the constructor of the
DatabaseContent class and ideally it should be opened up. Doing
this, you could add your own content store (that could extend an
existing one) and add the MimeTypes that this one supports.
I'm curious to see what you want to do with a custom IMAGE_JPEG
loader/formatter? What actually happens is that RIFE tried to
load any possible image, not just JPEGS. To do this is goes over
the image loader backends it knows about. These are setup in
ImageContentLoader. Ideally, this order should also become
configurable. The JPEG type is only used for the format of the
final image storage (the loaded image will be transformed into
the target type). If you just want to store anything as-is, use
the RAW type. Note that you can always change and interact with
your content by using a ContentTransformer. We chose to use the
standard java.awt.Image type as the format into which to load
the images before writing them out again. If you want another
type, you can use the RAW type with your own ContentTransform to
handle it the way you want.
Hope this helps.
Best regards,
Geert
On 08 Dec 2006, at 17:56, Joshua Hansen wrote:
Hi Geert (and others),
I've been working a little with the CMF and I was wondering: is
it possible to specify a custom MimeType class? I can't extend
it because the constructor is private, and I can't reset the
static enum defs (IMAGE_JPEG, IMAGE_PNG, etc) with custom
versions for the same reason.
I'd like to add new MimeTypes, and or replace existing types,
such as to use a custom IMAGE_JPEG loader/formatter. A
specific example would be to use a more efficient third party
or native library for image manipulation/handling (instead of
java.awt.Image).
I'm using RIFE 1.4.
Shalom (complete peace),
Josh
_______________________________________________
Rife-users mailing list
[email protected]
http://lists.uwyn.com/mailman/listinfo/rife-users
--Geert Bevin
Uwyn "Use what you need" - http://uwyn.com
RIFE Java application framework - http://rifers.org
Music and words - http://gbevin.com
_______________________________________________
Rife-users mailing list
[email protected]
http://lists.uwyn.com/mailman/listinfo/rife-users
_______________________________________________
Rife-users mailing list
[email protected]
http://lists.uwyn.com/mailman/listinfo/rife-users
--
Geert Bevin
Uwyn "Use what you need" - http://uwyn.com
RIFE Java application framework - http://rifers.org
Music and words - http://gbevin.com
_______________________________________________
Rife-users mailing list
[email protected]
http://lists.uwyn.com/mailman/listinfo/rife-users
_______________________________________________
Rife-users mailing list
[email protected]
http://lists.uwyn.com/mailman/listinfo/rife-users
--
Geert Bevin
Uwyn "Use what you need" - http://uwyn.com
RIFE Java application framework - http://rifers.org
Music and words - http://gbevin.com
_______________________________________________
Rife-users mailing list
[email protected]
http://lists.uwyn.com/mailman/listinfo/rife-users