A better way to organize my case of SetAttribute?
Hi,
I am developing a JSP page that handles saving. It handles multiple page status. Depending on the status, the page needs to save a certain set of fields in the database table.
In my JSP submit page, i have put 3 clusters of jbo:setAttribute commands to cater to the 3 scenarios:
<% if (strStatus.equals("Creation")) { %>
<jbo:SetAttribute dataitem="A" value="abc" />
<jbo:SetAttribute dataitem="B" value="abc" />
<jbo:SetAttribute dataitem="C" value="abc" />
<jbo:SetAttribute dataitem="D" value="abc" />
<% } else if (strStatus.equals("Pending")) { %>
<jbo:SetAttribute dataitem="B" value="abc" />
<jbo:SetAttribute dataitem="C" value="abc" />
<jbo:SetAttribute dataitem="D" value="abc" />
<% } else if (strStatus.equals("Confirming")) { %>
<jbo:SetAttribute dataitem="B" value="abc" />
<jbo:SetAttribute dataitem="C" value="abc" />
<% } %>
This is just a basic example, in my case, there are many status and each status updates a certain set of fields in the database table.
I was wondering, how should I reduce or make my code easier to maintain for this? Maybe I could repeat the whole lot of SetAttribute from A to D for each status, provided, there is a flag like maybe <jbo:setattribute dataitem="" value="" toset="true">
So in that case, all i need during development is just duplicate one similar stack of setattribute for every status and then look through, whichever field that needs to be inserted/updated, I will put the flag to true, if i put it to false, that means the SetAttribute is not supposed to do anything.
The reason I want to make my code easier to read/maintain is that my database fields are still volatile, they can be changed or renamed anytime, so if I were to have different permutations of the setattribute for each case/status, any sudden changes of database fields will require me to look though every group of SetAttribute tag to correct it.
I was thinking maybe there might be a better design to cater to this issue.
Any ideas are appreciated. Thank you.
Edited by: user11291846 on Jun 22, 2009 6:45 AM
Edited by: user11291846 on Jun 22, 2009 6:48 AM
You're not really telling us very muc about your current system there, so here's a generic answer that might spark some ideas for you.
I use Events simply as big buckets of Photos: Spring 08, July - Nov 06 are typical Events in my Library. I use keywords and Smart Albums extensively. I title the pics broadly.
I keyword on a
Who
What
Where basis (The When is in the photos's Exif metadata). I also rate the pics on a 1 - 5 star basis.
Using this system I can find pretty much find any pic in my 40k library in a couple of seconds.
So, for example, I have a batch of pics titled 'Seattle 08' and a typical keywording might include: John, Anne, Landscape, mountain, trees, snow. With a rating included it's so very easy to find the best pics we took at Mount Rainier.
File -> New Smart Album
set it to 'All"
title contains Seattle
keyword is mountain
keyword is snow
rating is 5 stars
Or, want a chronological album of John from birth to today?
New Smart Album
Keyword is John
Set the View options to Sort By Date Ascending
Want only the best pics?
add Rating is greater than 4 stars
The best thing about this system is that it's dynamic. If I add 50 more pics of John to the Library tomorrow, as I keyword and rate them they are added to the Smart Album.
In the end, organisation is about finding the pics. The point is to make locating that pic or batch of pics findable fast. This system works for me.
Similar Messages
-
Exist an app to watch the system logs in a better way? More organize?
HI,
Every time that I present a portal issue I past hours verifing portal logs, etc to find the issues occurred..
Exist an app or a way to watch the logs in a better way?
Thanks!
CarlosHi,
You can use log4j for logging. You can write your logs wherever you want and categorize it.
You can view an example: http://nwturk.com/blog/2010/04/16/logging-using-log4j-in-java-applications/ -
Must be a better way...
Hello Flash Community!
Thanks in advance for any help/advice.
So, what I'm looking for here is some high level advice as far as a better way to do things. I feel like so often with programming I'm just breaking my neck to get things working when I know there is a better way (presumably based in OOP) to go about things. I just need someone to look at what I've done and point it out to me.
So, here's what I've done so far: http://www.catherinemix.com
And it works pretty well as far as I'm concerned! The app dynamically loads as many images as my client (my mom ) puts on the server, resizes them dynamically, adds L/R arrow buttons dynamically based on how many images are involved, etc... But the downside to all that dynamic flexibility is that I haven't found a way to load the thumbnail images (and their respective full size images) one by one. Instead, I have to load them all together and keeping the user waiting that long is unacceptable to my mom. What I would love is for each thumbnail/full size combo to get its own preloader bar in the location it will eventually be embedded, but I haven't found a way to do that and account for an unknown number of images (as it is determined dynamically.)
Any ideas here? I would specifically like to know which functions y'all use when you need to load multiple files simultaenously (AttachMovie?)
I have posted the kluge-y code which handles all of the image gallery functions below.
Thanks! and Be Well
Graham
import fl.transitions.Tween;
import fl.transitions.easing.*;
var wait:PleaseWait = new PleaseWait();
wait.x = 400;
wait.y = 50;
addChild(wait);
var waitFadeIn:Tween = new Tween(wait, "alpha", Regular.easeOut, 0, 1, 1, true);
var titleText:TextField;
var textSprite:Sprite;
//thumbH is the ideal height for our thumbnails, and thumbW the ideal width
var thumbH = 120;
var thumbW = 170;
//loadH is the ideal height for our fullsize images, and loadW the ideal width
var loadH = 500;
var loadW = 600;
//some counter numbers
var thumbNum = 1;
var loadNum = 1;
//some Sprites which need to be accessed by more than one function
var darkStage:Sprite;
var loadSprite:Sprite;
//Let's instantiate some Arrays that we can load the images into.
//Since Arrays of Loaders can't be copied, we have to go through the process twice.
var thumbArray:Array = new Array();
var loadArray:Array = new Array();
firstLoad();
firstThumb();
function firstLoad():void {
trace("firstLoad");
var loadski = new Loader();
loadski.load(new URLRequest("images/fulls/0.png"));
loadski.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);
loadArray.push(loadski);
//Starting with the above Loader, this function will execute every time the Loader completes
function loadComplete(e:Event):void {
trace("loadComplete");
var loadski = new Loader();
loadski.load(new URLRequest("images/fulls/" + loadNum + ".png"));
loadArray.push(loadski);
loadski.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);
loadski.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, loadError);
loadNum++;
//Once the Loader goes too far by attempting to load an image that doesn't exist on the computer,
//it will thorw an IOError Event at which point the following function will execute.
function loadError(e:IOErrorEvent):void {
trace("loadError");
loadArray.pop();
loadNum = 0;
loadResize();
//We use the pop function to remove the most recently added Loader instance, since we know it
//contains a null reference (beacuse the IOError Event is asynchronous.)
thumbArray.pop();
//We reset the counter variable.
thumbNum = 0;
//Add the little arrows that allow the user to click to see more thumbnails (if there are more
//than 8 images on the server.)
removeChild(wait);
addArrows();
//Let's resize the images to thumbnail size and add them to the display list.
thumbResize();
addClickOnThumb();
function loadResize():void {
trace("loadResize");
for (var ex = 0; ex < loadArray.length; ex++) {
//If the width of the image is greater than the ideal width, OR the height is greater than the ideal height...
if ( loadArray[loadNum].content.width > loadW || loadArray[loadNum].content.height > loadH) {
//And if the width of the image is greater than the height, apply Scaler 1...
if ( loadArray[loadNum].content.width > loadArray[loadNum].content.height ) {
//Scaler 1 is the ratio of the ideal width to the image width
var scaler1 = loadW / loadArray[loadNum].content.width;
trace(loadNum + " load scaler 1: " + scaler1);
//Apply Scaler 1 to both the width and height of the image
loadArray[loadNum].content.scaleX = loadArray[loadNum].content.scaleY = scaler1;
//Otherwise, apply Scaler 2
} else {
//Scaler 2 is the ratio of the ideal width to the image height
var scaler2 = loadH / loadArray[loadNum].content.height;
trace(loadNum + " load scaler 2: " + scaler2);
//Apply Scaler 2 to both the width and height of the image
loadArray[loadNum].content.scaleX = loadArray[loadNum].content.scaleY = scaler2;
trace("loadArray[loadNum].content.height = " + loadArray[loadNum].content.height);
trace("loadArray[loadNum].content.width = " + loadArray[loadNum].content.width);
//Otherwise... (that is, the image width and height are in both cases less than the ideal)
} else {
//And if the width of the image is greater than the heigh, apply Scaler 3
if ( loadArray[loadNum].content.width > loadArray[loadNum].content.height ) {
//Scaler 3 is the ratio of the ideal width to the image width
var scaler3 = loadW / loadArray[loadNum].content.width;
trace(loadNum + " load scaler 3: " + scaler3);
//Apply Scaler 3 to both the width and height of the image
loadArray[loadNum].content.scaleX = loadArray[loadNum].content.scaleY = scaler3;
} else {
//Scaler 4 is the ratio of the ideal width to the image height
var scaler4 = loadH / loadArray[loadNum].content.height;
trace(loadNum + " load scaler 4: " + scaler4);
//Apply Scaler 4 to both the width and height of the image
loadArray[loadNum].content.scaleX = loadArray[loadNum].content.scaleY = scaler4;
loadArray[loadNum].content.x = - (loadArray[loadNum].content.width / 2);
loadArray[loadNum].content.y = - (loadArray[loadNum].content.height / 2);
loadNum++;
function firstThumb():void {
trace("firstThumb");
//Let's populate the first Array with Loaders that load the images Mom has put on the server.
//We have to do this first Loader object by hand to get the Event.COMPLETE-based-loop going.
var thumbski = new Loader();
thumbski.load(new URLRequest("images/thumbs/0.png"));
thumbski.contentLoaderInfo.addEventListener(Event.COMPLETE, thumbComplete);
//We add the MouseEvent.CLICK listener to the actual Loader instance so that, later on, in the
//function enLarge, we can make use of the currentTarget parameter to correlate the Array index of
//the thumbnail that the user is clicking on with that of the loadArray.
thumbski.addEventListener(MouseEvent.CLICK, enLarge);
thumbArray.push(thumbski);
//Starting with the above Loader, this function will execute every time the Loader completes
function thumbComplete(event:Event):void {
trace("thumbComplete");
var thumbski = new Loader();
thumbski.load(new URLRequest("images/thumbs/" + thumbNum + ".png"));
thumbski.contentLoaderInfo.addEventListener(Event.COMPLETE, thumbComplete);
//We add the IOErrorEvent listener so that as soon as this error is thrown, we will exit this loop
//and proceed to the next logical step in the program can be taken.
thumbski.addEventListener(MouseEvent.CLICK, enLarge);
thumbArray.push(thumbski);
thumbNum++;
function addArrows():void {
//Let's determine how many batches there are. A batch is the minimum amount of thumbnail images
//mom wants to show up onscreen at a time. In this case, she has decided on 8.
var batches = Math.ceil(thumbArray.length / 8);
//The variable m is part of a kluge fix related to the calculation of startX (explained below.)
var m = 0;
//Pseudocode for this loop: If there are at least two batches, then...
//We do this because less than 2 batches doesn't warrant arrows
if (batches > 1) {
for (var k = 1; k < batches; k++) {
//triW is the desired width of our arrows
var triW = 20;
//startX is the x position of the start of our rightward facing triangle(s)
//The formula says: Our x starting position should be a triangle width shy of the
//far edge of the stage (multiplying it by k ensures it happens as many times
//as there are batches, which is why we intialize k = 1.) Every subsequent iteration
//of the formula has to add a triangle's width worth of distance, except for the
//very first one, which is why it is multiplied by m, which is initially set to 0.
var startX = (((stage.stageWidth - triW) * k) + (triW * m));
//We want the arrows to sit perfectly between the two rows of thumbnails. Since the
//max height of every thumbnail is thumbW, that would seem to be the natural choice
//for the starting y position of the arrows. But, we actually have to use thumbW/2
//because the thumbnails have already been offset by half of thumbW due to being
//aligned vertically with each other.
var startY = (thumbW / 2);
//This is the rightward facing triangle
var tri:Sprite = new Sprite();
tri.graphics.beginFill(0xFFFFFF);
tri.graphics.moveTo(startX, startY);
tri.graphics.lineTo(startX, (startY + triW));
tri.graphics.lineTo((startX + triW), (startY + (triW/2)));
tri.graphics.lineTo(startX, startY);
tri.graphics.endFill();
tri.buttonMode = true;
tri.useHandCursor = true;
tri.addEventListener(MouseEvent.CLICK, moveLeft);
addChild(tri);
//This is the leftward facing triangle
var tri2:Sprite = new Sprite();
var startX2 = (startX + (triW * 2));
tri2.graphics.beginFill(0xFFFFFF);
tri2.graphics.moveTo(startX2, startY);
tri2.graphics.lineTo(startX2, (startY + triW));
tri2.graphics.lineTo((startX2 - triW), (startY + (triW / 2)));
tri2.graphics.lineTo(startX2, startY);
tri2.graphics.endFill();
tri2.buttonMode = true;
tri2.useHandCursor = true;
tri2.addEventListener(MouseEvent.CLICK, moveRight);
addChild(tri2);
//Increase m (see above)
m++;
//This function moves the entire Gallery MovieClip to the left 800 pixels.
function moveLeft(event:MouseEvent):void {
var leftTween:Tween = new Tween(this, "x", Regular.easeOut, this.x, (this.x - 800), .5, true);
//This function moves the entire Gallery MovieClip to the right 800 pixels.
function moveRight(event:MouseEvent):void {
var rightTween:Tween = new Tween(this, "x", Regular.easeOut, this.x, (this.x + 800), .5, true);
//This function resizes the loaded images to the desired thumbnail dimensions and adds them
//to the display list.
function thumbResize():void {
//The highest level of organization of thumbnails is the batch. There are only as many batches
//as the length of the thumbArray divided by 8 (the max amount of thumbnails in a batch, as determined
//by mom.)
for (var batch = 0; batch < Math.ceil(thumbArray.length / 8); batch++) {
trace("batch " + batch);
//This Sprite serves as the container that we use to position entire batches
var batchSprite: Sprite = new Sprite();
//The logic behind setting the x position of the batchSprite to 800 x batch should be self-evident --
//we want each new batch to be 800 pixels to the right of the former one -- but the addition of (thumbW
//divided by 1.5) is a kluge fix for how much space to give the batches on left margin.
batchSprite.x = (thumbW / 1.5) + (batch * 800);
addChild(batchSprite);
//The second highest level of organization for our thumbnails is the row. Our grid of thumbnails is
//two rows deep.
for (var row = 0; row < 2; row++) {
trace(" row " + row);
//The third highest level of organization for our thumbnails is the column. Our grid of thumbnails is
//four columns deep.
for (var col = 0; col < 4; col++) {
trace(" col " + col);
trace(" thumb " + thumbNum);
if (thumbNum < thumbArray.length) {
//The following is the logic structure for handling the resizing of images. The goal was to develop
//a system robust enough to allow my mom to put whatever size images she wanted on the server and the
//app would use them. The logic is explained at each step...
//If the width of the image is greater than the ideal width, OR the height is greater than the ideal height...
if ( thumbArray[thumbNum].content.width > thumbW || thumbArray[thumbNum].content.height > thumbH) {
//And if the width of the image is greater than the height, apply Scaler 1...
if ( thumbArray[thumbNum].content.width > thumbArray[thumbNum].content.height ) {
//Scaler 1 is the ratio of the ideal width to the image width
var scaler1 = thumbW / thumbArray[thumbNum].content.width;
trace(" scaler1 = " + scaler1);
//Apply Scaler 1 to both the width and height of the image
thumbArray[thumbNum].content.scaleX = thumbArray[thumbNum].content.scaleY = scaler1;
trace(" image width:" + thumbArray[thumbNum].content.width);
trace(" image height:" + thumbArray[thumbNum].content.height);
//Otherwise, apply Scaler 2
} else {
//Scaler 2 is the ratio of the ideal width to the image height
var scaler2 = thumbW / thumbArray[thumbNum].content.height;
trace(" scaler2 = " + scaler2);
//Apply Scaler 2 to both the width and height of the image
thumbArray[thumbNum].content.scaleX = thumbArray[thumbNum].content.scaleY = scaler2;
trace(" image width:" + thumbArray[thumbNum].content.width);
trace(" image height:" + thumbArray[thumbNum].content.height);
//Otherwise... (that is, the image width and height are in both cases less than the ideal)
} else {
//And if the width of the image is greater than the heigh, apply Scaler 3
if ( thumbArray[thumbNum].content.width > thumbArray[thumbNum].content.height ) {
//Scaler 3 is the ratio of the ideal width to the image width
var scaler3 = thumbW / thumbArray[thumbNum].content.width;
trace(" scaler3 = " + scaler3);
//Apply Scaler 3 to both the width and height of the image
thumbArray[thumbNum].content.scaleX = thumbArray[thumbNum].content.scaleY = scaler3;
trace(" image width:" + thumbArray[thumbNum].content.width);
trace(" image height:" + thumbArray[thumbNum].content.height);
} else {
//Scaler 4 is the ratio of the ideal width to the image height
var scaler4 = thumbW / thumbArray[thumbNum].content.height;
trace(" scaler4 = " + scaler4);
//Apply Scaler 4 to both the width and height of the image
thumbArray[thumbNum].content.scaleX = thumbArray[thumbNum].content.scaleY = scaler4;
trace(" image width:" + thumbArray[thumbNum].content.width);
trace(" image height:" + thumbArray[thumbNum].content.height);
//Here is where we center the images vertically...
thumbArray[thumbNum].content.x = - (thumbArray[thumbNum].content.width / 2);
//Here is where we center the images horizontally...
thumbArray[thumbNum].content.y = - (thumbArray[thumbNum].content.height / 2);
//Before placing them in their own container Sprite, so that their relative positions can be
//determined accurately (a task that would've been otherwise impossible after the
//adjustments to position made above.)
var thumby = new MovieClip();
thumby.addChild(thumbArray[thumbNum]);
//thumbW being the max possible length or width of any one thumbnail (this was done for visual
//consistency and codified in the logic tree above), placing two thumbnails thumbW
//apart (measuring from center point in either case) will put them edge to edge at best. This is why
//we add (thumbW / 8) as additional spacing.
thumby.y = (row * (thumbW + (thumbW / 8)));
thumby.x = (col * (thumbW + (thumbW / 8)));
thumby.buttonMode = true;
thumby.useHandCursor = true;
var fA:Array = new Array();
var dS:DropShadowFilter = new DropShadowFilter(5, 45, 0x000000, 0.33, 5, 5, 1, 1);
fA.push(dS);
thumby.filters = fA;
trace("thumby.width = " + thumby.width);
trace("thumby.height = " + thumby.height);
batchSprite.addChild(thumby);
thumbNum++;
function enLarge(event:MouseEvent):void {
var indexNum:Number = new Number();
indexNum = thumbArray.indexOf(event.currentTarget);
trace("indexNum = " + indexNum);
darkStage = new Sprite();
darkStage.graphics.beginFill(0x333333, .9);
darkStage.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
darkStage.addEventListener(MouseEvent.CLICK, reMove);
darkStage.buttonMode = true;
darkStage.useHandCursor = true;
(parent as MovieClip).addChild(darkStage);
loadSprite = new Sprite();
loadSprite.addChild(loadArray[indexNum]);
loadSprite.x = (stage.stageWidth / 2);
loadSprite.y = (stage.stageHeight / 2);
loadSprite.addEventListener(MouseEvent.CLICK, reMove);
loadSprite.buttonMode = true;
loadSprite.useHandCursor = true;
loadSprite.mouseEnabled = false;
(parent as MovieClip).addChild(loadSprite);
var urlRequest:URLRequest = new URLRequest("xmls/" + indexNum + ".xml");
var titleURL:URLLoader = new URLLoader();
titleURL.addEventListener(Event.COMPLETE, completeListener);
titleURL.load(urlRequest);
function completeListener(event:Event):void {
titleText = new TextField();
titleText.autoSize = TextFieldAutoSize.LEFT;
var myFont:Font = new BOF();
var ttFormat:TextFormat = new TextFormat();
ttFormat.color = 0xFFFFFF;
ttFormat.size = 18;
ttFormat.font = myFont.fontName;
textSprite = new Sprite();
textSprite.addChild(titleText);
(parent as MovieClip).addChild(textSprite);
var titleXML:XML = new XML(titleURL.data);
titleText.text = titleXML.toXMLString();
titleText.setTextFormat(ttFormat);
titleText.embedFonts = true;
textSprite.y = 570;
textSprite.x = ((stage.stageWidth / 2) - (titleText.textWidth / 2));
textSprite.mouseEnabled = false;
titleText.mouseEnabled = false;
function reMove(event:MouseEvent):void {
(parent as MovieClip).removeChild(textSprite);
(parent as MovieClip).removeChild(loadSprite);
(parent as MovieClip).removeChild(darkStage);
function addClickOnThumb():void {
var cot:ClickOnThumbnail = new ClickOnThumbnail();
cot.x = 400;
cot.y = 583;
(parent as MovieClip).addChild(cot);Hey Jim
Wow, that's great; thanks! Can I ask what settings you used to get the files so small?
Yes, I am familiar with Photoshop and image optimization issues, but I didn't realize that PNG was so much bigger than JPG and that I had so much file size I could shed before I would notice a degradation in image quality. Your advice will certainly help greatly, and I will certainly apply it to the thumbs as well. I think my mom will be very pleased. : )
I look forward to hearing what collection of settings you used.
Thanks and Be Well
Graham -
What is the best way to organize a tree-like structure of constants?
Hello everone!
Need help with organizing my constants structrure.
I have several tables, and each of them need a list of column names to define the fields returned after query, and also a corresponding list of hashmap keys because that columnnames are ugly. Hashmap is where I store the result of searching through the table. This question is not about JDBC because I search through tables via COM interface, no JDBC ResultSets and other stuff here.
Finally, for each table I have two constant lists and I have a list of tables. What is the best way to store this?
My first idea was to create a enum and store column data in it as String array attributes: String[] columnNames; etc.
But in this case I cannot use each column and key separately.
Another option is to create two separate enums for each table: columnNames enum and keys enum. That doesn't look great also.
The third option is to create inner class for each table and store two enums in each of that classes.
Also I can store all data in hashmaps, Strings etc.
(1) Finally, from your experience, what is the best way to organize all that stuff?
(2) I have heard that smart Java programmer should avoid using the enums by any means. Do you agree?
(3) Generally what will you prefer when creating a constant which has two values: two final Integers or enum?
Edited by: Dmitry_MSK on Jul 8, 2010 5:22 AMI'm not sure why you don't just invent a generic data structure (e.g., table name, list of column names and aliases of column names) such as:
class QueryMetaData {
private final String tableName;
private final String[] columnNames;
private final String[] columnAliases;
}Read into the above structure from a properties file, database table, etc. You can store meta-data itself in places other than enum constants, particularly if would like to change the meta-data without requiring a new build of your application.
That having been said, WRT to your specific questions:
(1) Finally, from your experience, what is the best way to organize all that stuff?See above
(2) I have heard that smart Java programmer should avoid using the enums by any means. Do you agree?Enums are better than simple constants using int or String or something similar. If there are known, discrete values unlikely to change frequently, I see no issues with an enum. They improve the readability of code, and there are enough syntactic sugar features in the language (switch statements come to mind) to make them appealing.
(3) Generally what will you prefer when creating a constant which has two values: two final Integers or enum?
See above. Enums were introduced (in large part) to do away with storing constants as integers.
- Saish -
What is the easiest and faster way to organize my itunes library
I've been building my itunes library for many years and for many reasons this library has become a complete chaos. I have around 50,000 songs, which 10,000 of those I can't locate the file in my hard drive maybe for the following reasons:
- the incomplete transfer of data from my old imac to the new one (besides loosing music files, I lost a ton of pictures and docs)
- the internal hard drive got full and had to delete all the storaged data
- change of location for my backup files. Locations were first the internal hard drive and after that the external 3T hard drive
- unknown computer behavoir. The computer changed the location within the external hard drive
Also, duplicate files that need to be deleted, those are around 2,000 more and less
I thought about just coping all my media files to an external hard drive, clean my itunes account of all those files down to cero and reload the media files into my account making sure all those files are located and stay in only one place.
All of this is time consuming which i don't have and I would like to see if there's a better wayt to organize it either using an external software or any other way I'm nopt aware of.
Any ideas?.......I like to go via computer first in most cases and then Bluetooth, SD and SIM cards but it is what you can handle and have to work with also. Wish you the best.
-
Hi, everyone!
INTRO: I'm new to Lightroom. I've gone through a few books and lots of tutorial courses on lynda and youtube, so I feel quite comfortable with LR 5's import process. This post and question is a pre-import/organizational issue.
I have more than 30,000 old, digitized (scanned) photos dating back to the 1950s. Obviously, most of were taken with old, analog cameras. These are now organized into folders by date.
GOAL: I want to import these photos into LR and be able to find them by metadata dates (Capture Date & Time).
PROBLEM: Obviously, old scanned (or even more recent manipulated) photos often don't have the correct EXIF creation date info. Even worse, many (or most) of these old images don't even have an EXIF date field!
WHAT I'VE LEARNED: Using exiv2 filename or evix2 -pt filename immediately shows whether there is or is not date info for the photo. If there isn't, exiv2 -pt filename shows nothing. If there is an EXIF date field, it will be shown.
For all these images with no date field, if I import them into Lightroom, there of course is no date info that shows up in the Metadata panel (under Default or EXIF), nor can you change the date (because the field isn't even there).
If exiv2 -pt filename DOES show the Exif.Image.DateTime field, then in Lightroom, you will see the Capture Time and Capture Date fields, and you will see an icon to the right of those dates that allows you to change that date.
If exiv2 -pt filename DOES NOT show this Exif.Image.DateTime field, you can ADD this field by using the command line:
exiv2 -M"set Exif.Image.DateTime Ascii 1965:01:25 15:45:00" filename (or whatever your date/time is).
Now if you import this image into LR, you will find the Capture Time and Capture Date fields under the Metadata > Default panel...AND you can edit them if needed. That is, the above exiv2 -M command added the EXIF date field that LR needs in order to search by date.
WHAT'S MY POINT, AND WHAT'S MY QUESTION? I have no problem using exiv2 to add/change an EXIF creation DateTime field one folder at a time prior to importing them into LR. This will enable me to search on those date fields**.
My question is this: Is there an easier method?
Surely there must be tens (hundreds?) of thousands of "older" photographers like myself who have troves of old photos that have incorrect EXIF creation date fields, or missing the date field entirely (in which case, as I stated above, cannot be added/edited using LR, PS, FileMultiTool, Graphic Converter, etc.).
I realize that I could look at images based on the folder names or file names, or I could enter dates into tags, but such methods of finding images are not nearly as convenient as using Metadata. Therefore, if I know that an image was taken in June 1962, then I'd like the EXIF metadata to have this info so that I can search on it. To have no EXIF date field or to have a date field that is incorrect is useless.
I'D LOVE YOUR COMMENTS! If there is an easier or better way, I'd love for you to help! There are so many experienced photographers on this forum, and more than likely many of them have old photos with incorrect or missing EXIF date fields that they've brought into LR.
THANKS! I'll really appreciate any and all help you can offer.
David
** there are other EXIF date fields that can be changed using exiv2: Exif.Photo.DateTimeOriginal, Exif.Photo.DateTimeDigitized, etc. But the principal date that LR uses to search for files is the one described above.
P.S. I've also tried jhead -ds1965:01:25 filename (or whatever your date is) to change the date. This works ONLY IF there is already an EXIF date field present. If not, jhead will report an error and not create one. exiv2 -M will create the field.John,
Thanks very much for your help! I had tried the plugin, exiv2, exiftool, and LR's Metadata menu option only on a single photo.
You are 100% correct about LR's menu option assigning different times! Thank you for pointing this out.
When I set the date and time for about 10 photos, LR's menu option assigned (seemingly random!) times to all of them. Why would LR do this? I can perhaps see offsetting each photo by 1 second (00, 01, 02,...), but simply assigning random times makes no sense at all. At least in the tests I just did, LR didn't shift the time by the same amount, but assigned totally (random?) times to every photo.
Another problem that I found with the LR menu item is that it failed to change the date/time at all for several of the images I selected! The Capture Time To Exif plugin, exiv2, and exiftool had no problem at all with the same photos.
I also looked at the ExifMeta by Rob Cole that you mentioned. It looks very powerful (and is free), but much more complex than what I need at this point.
Therefore, I purchased the Capture Time To Exif plugin, and it works great on multiple photos.
I now have good methods to change the date for multiple images:
1. Prior to import: exiv2 or exiftool
2. After import: John's Capture Time To Exif plugin
Thank you again for your help!
This brings me one step closer to importing my photos in a logical method.
David -
Need help to get alternate or better way to write query
Hi,
I am on Oracle 11.2
DDL and sample data
create table tab1 -- 1 millions rows at any given time
id number not null,
ref_cd varchar2(64) not null,
key varchar2(44) not null,
ctrl_flg varchar2(1),
ins_date date
create table tab2 -- close to 100 million rows
id number not null,
ref_cd varchar2(64) not null,
key varchar2(44) not null,
ctrl_flg varchar2(1),
ins_date date,
upd_date date
insert into tab1 values (1,'ABCDEFG', 'XYZ','Y',sysdate);
insert into tab1 values (2,'XYZABC', 'DEF','Y',sysdate);
insert into tab1 values (3,'PORSTUVW', 'ABC','Y',sysdate);
insert into tab2 values (1,'ABCDEFG', 'WYZ','Y',sysdate);
insert into tab2 values (2,'tbVCCmphEbOEUWbxRKczvsgmzjhROXOwNkkdxWiPqDgPXtJhVl', 'ABLIOWNdj','Y',sysdate);
insert into tab2 values (3,'tbBCFkphEbOEUWbxATczvsgmzjhRQWOwNkkdxWiPqDgPXtJhVl', 'MQLIOWNdj','Y',sysdate);I need to get all rows from tab1 that does not match tab2 and any row from tab1 that matches ref_cd in tab2 but key is different.
Expected Query output
'ABCDEFG', 'WYZ'
'XYZABC', 'DEF'
'PORSTUVW', 'ABC'Existing Query
select
ref_cd,
key
from
select
ref_cd,
key
from
tab1, tab2
where
tab1.ref_cd = tab2.ref_cd and
tab1.key <> tab2.key
union
select
ref_cd,
key
from
tab1
where
not exists
select 1
from
tab2
where
tab2.ref_cd = tab1.ref_cd
);I am sure there will be an alternate way to write this query in better way. Appreciate if any of you gurus suggest alternative solution.
Thanks in advance.Hi,
user572194 wrote:
... DDL and sample data ...
create table tab2 -- close to 100 million rows
id number not null,
ref_cd varchar2(64) not null,
key varchar2(44) not null,
ctrl_flg varchar2(1),
ins_date date,
upd_date date
insert into tab2 values (1,'ABCDEFG', 'WYZ','Y',sysdate);
insert into tab2 values (2,'tbVCCmphEbOEUWbxRKczvsgmzjhROXOwNkkdxWiPqDgPXtJhVl', 'ABLIOWNdj','Y',sysdate);
insert into tab2 values (3,'tbBCFkphEbOEUWbxATczvsgmzjhRQWOwNkkdxWiPqDgPXtJhVl', 'MQLIOWNdj','Y',sysdate);
Thanks for posting the CREATE TABLE and INSERT statments. Remember why you go to all that trouble: so the people whop want to help you can re-create the problem and test their ideas. When you post statemets that don't work, it's just a waste of time.
None of the INSERT statements for tab2 work. Tab2 has 6 columns, but the INSERT statements only have 5 values.
Please test your code before you post it.
I need to get all rows from tab1 that does not match tab2 WHat does "match" mean in this case? Does it mean that tab1.ref_cd = tab2.ref_cd?
and any row from tab1 that matches ref_cd in tab2 but key is different.
Existing Query
select
ref_cd,
key
from
select
ref_cd,
key
from
tab1, tab2
where
tab1.ref_cd = tab2.ref_cd and
tab1.key <> tab2.key
union
select
ref_cd,
key
from
tab1
where
not exists
select 1
from
tab2
where
tab2.ref_cd = tab1.ref_cd
Does that really work? In the first branch of the UNION, you're referencing a column called key, but both tables involved have columns called key. I would expect that to cause an error.
Please test your code before you post it.
Right before UNION, did you mean
tab1.key != tab2.key? As you may have noticed, this site doesn't like to display the <> inequality operator. Always use the other (equivalent) inequality operator, !=, when posting here.
I am sure there will be an alternate way to write this query in better way. Appreciate if any of you gurus suggest alternative solution.Avoid UNION; it can be very inefficient.
Maybe you want something like this:
SELECT tab1.ref_cd
, tab1.key
FROM tab1
LEFT OUTER JOIN tab2 ON tab2.ref_cd = tab1.ref_cd
WHERE tab2.ref_cd IS NULL
OR tab2.key != tab1.key
; -
A better way to execute a series of external commands?
Hi,
Consider the code snippet...
Process proc1 = rt.exec("Some external command");
Vector vecOutput = outputGobbler.getOutput() ;
String[] strAlterCmds = new String[vecOutput.size()];
for ( int k = 0 ; k < vecOutput.size() ; k++ )
strAlterCmds[k] = new String();
strAlterCmds[k] = "cmd.exe /c blah.... " +(String) vecOutput.elementAt( k )+ " ;
Process proc2 = rt.exec(strAlterCmds[k], null);
StreamGobbler errorG = new
StreamGobbler( proc2.getErrorStream(), "Error") ;
StreamGobbler outputG = new
StreamGobbler( proc2.getInputStream(), "Output") ;
errorG.start() ;
outputG.start() ;
int exitVal1 = proc2.waitFor();
The second part of the execution is taking AGES and I am not sure forking a new process for runtime execution is the best alternative here.
I would be glad if someone can point me to a smarter solution.
In short: I intend to execute a series of commands using RTE depending on the values I get in the loop.
Thanks.Jared,
Thank you for responding to my posted message. Rendezvous is a new concept to me, maybe
it's the solution to my problem. I have been trying to read the on line manual and
example VIs from National Instruments website. I still have a hard time to understand
the concept.
One of the example I saw is using rendezvous to run some sub VIs. But in my case, I have
only one VI that is a while loop. Inside the while loop, there are a few tasks running
simultaneously. I don't know whether it will serve my purpose.
Guangde Wang
Jared O'Mara wrote:
> Guangde,
>
> Referring to your 2nd method, use rendezvous (under advanced>>synchronize
> on function palette) to synchronize two processes. There are good examples
> that come with labview. basically, you cre
ate a rendezvous, giving it a
> size. Using the wait on rendezvous vi, a function will not continue until
> all rendezvous have reached that point. Using this method, you can synchronize
> your 2 while loops.
>
> Jared
>
> Guangde Wang wrote:
> >I tried two ways to control the tempo of my program.>>One is to use the
> While Loop's counter and a wait. The drawback of this>method is the cycle
> length is dependent on the measuring load. So if the>program runs for days,
> it will be significent off the real time.>>The other way is to use the difference
> of the Tick Count. It provides>accurate timing but the problem is the sychronization
> of the clock cycle>and the While Loop cycle. I can try to put a little bit
> wait but still>can not sychronize them very well. So after a while, there
> will be two>measures get together.>>I don't know whether there are some better
> ways to control the program>or whether we have some ways to improve either
> or both of the above
two>methods to make them work better. Please let me
> know if you have any>suggestion.>>Thank you in advance,>>Guangde Wang> -
A better way to do ChangeListeners?
I find myself having to implement multiple change listeners in a single class, and I was wondering if there was a way to do this that wouldn't trigger compilation problems. For example, let's say you have a LineChart, and you want the chart to listen for changes to the data, but also changes to the user's smoothing algorithm selection. You might try declaring your class like this:
public class MyGraph implements DataChangeListener, SmoothingChangeListener {....where you've declared DataChangeListener, and SmoothingChangeListener as
DataChangeListener extends ChangeListener<SomeDataStructure>{...}
SmoothingChangeListener extends ChangeListener<ISmoothable>{...}The compiler will tell you immediately that MyGraph can only implement one ChangeListener.
In real life, I have classes that have to listen for multiple types of events, and both for the sake of semantic clarity and for the sake of feasibility, they need to implement those change listeners. I've used event buses in certain cases, but they tend to obscure what the class is actually listening to.
Is there a better way of doing this?Event handling code is, almost by definition, controller code. So it makes sense (to me at least) to have event handling code in the controller. You can put the code I showed previously
someDataSeries.dataProperty().addListener(new ChangeListener<...>() {
public void changed(...) {
someChart.animatedProperty().addListener(new ChangeListener<Boolean>() {
public void changed(...) {
});directly in your controller. (I suppose I thought "MyGraph" was your controller, though the name should have implied otherwise to me.)
However, if you really want to have the event handlers defined elsewhere, you can still do so, while using anonymous inner classes (or lambdas when we all upgrade next September):
public class MyGraph {
private final ChangeListener<SomeDataType> dataListener = new ChangeListener<SomeDataType>() {
@Override
public void changed(...) { ... }
private final ChangeListener<ISmoothable> smoothingListener = new ChangeListener<ISmoothable>() {
@Override
public void changed(...) { ... }
public ChangeListener<SomeDataType> dataListener() { return dataListener ; }
public ChangeListener<ISmoothable> smoothingListener() { return smoothingListener ; }
}and you can then do
dataSource.addListener(myGraph.dataListener());
smoothingProperty.addListener(myGraph.smoothingListener());But I recommend the approach I first suggested: I use this all the time. -
A better way to initialize imported taskflows and BCs with current user
Hello.
I'm currently developing a composite application containing one main application and a number of subapplications (modules) packed in adflibs.
Main application has a side menu and a dynamic region, showing taskflows (on fragments) from adflibs.
Main application is configured with adf security and it has current login and queries his ID. I would like main application to tell modules current user ID rather than each module to find out current user on their own.
So there is currentUserID input parameter required in each imported taskflow. And my question is what is a better way to process this ID in the modules?
What I have previously done is:
I've created a custom BC classes layer, VOImpl and VORowImpl have getIdUser() method. This method reads currentUserID parameter from pageFlowScope where the taskflow is storing the parameter.
Top-level View Objects have :IdUser query parameter and corresponding bind variable. This bind variable has value="source.getIdUser()", calling the method from custom VO class.
This way works fine but here and there I read that it is a bad practice to access pageFlowScope from BCs.
I could agree with this in case someone could share a better way.
So what is a good practice?
Thanks.
ADF/JDev 11.1.2.3 - 12Why don't you use adf security for this? Read Oracle ADF: Security for Everyone which give you an overview and sample on how to implement this.
Timo -
A better way to generate the needed XML?
I am working on a 10.2 system and looking to see if there is a better way to generate the resulting XML than what I have come up with. Here is a test case and the output it generates. I don't really like querying the table for each column needed as the real table has eight columns I am pulling. I would like to make one pass on person_h and get the info needed instead of making eight passes, but not sure if it is possible.
with person_h as
(select 1 id, 'M' gender, 'W' race, '170' weight from dual union all
select 1, 'M', 'W', '170' from dual union all
select 1, 'M', 'W', '180' from dual union all
select 1, 'M', NULL, '175' from dual union all
select 1, NULL, 'W', NULL from dual
select xmlelement("Person",
(select xmlagg(xmlelement("Sex", gender))
from (select distinct gender
from person_h
where id = 1
and gender is not null) pg),
(select xmlagg(xmlforest(race as "Race"))
from (select distinct race
from person_h
where id = 1) pg),
(select xmlagg(xmlforest(weight as "Weight"))
from (select distinct weight
from person_h
where id = 1) pg)
).getstringval()
from dual;
Output
<Person>
<Sex>M</Sex>
<Race>W</Race>
<Weight>170</Weight>
<Weight>175</Weight>
<Weight>180</Weight>
</Person>Note: Previously posted on the XML DB forum at A better way to generate the needed XML? but still looking for other solutions so putting in front of more eyes here. I have considered using a WITH statement to do the initial query on person_h but haven't tested that yet to see what Oracle really will do as just getting back around to this lower priority task of mine.I'm using the WITH statement to simulate a table and DUAL/UNION ALL to create data in that "table". I've seen it used plenty of times in this forum so not sure why a problem for this example. The actual SQL/XML statement hits that "base table" three times, so I didn't include all eight columns because three columns is sufficient to show the problem in the way I coded the SQL. Following the SQL is the sample OUTPUT that SQL statement generates and that is the output I created and need. I'm just looking for other options to achieve the listed output.
-
A better way to Re-Order the Sort in Pivot view ?
Hello,
Question first- Is there a better way to do this?
Background- Have a simple pivot table w/ requirements to put the Status column in order that makes sense to the business not alphabetical.
Example, # of Service Req with Status needs to be listed as Assigned, Accepted, Completed, Closed, Re-assigned.
My solution was to create a column iin table view, use a CASE statement to say when Accepted =1 etc. I then sorted ASC, hid the column in table view and then pivot view I added Status column and hid the new CASE column. I am getting the results I expected but I was wondering if there was a better way to do this?
Thanks- NeallyAs far as the Presentation Layer is concernd (i.e., in Answers) your way is the best I can think of. The only way you can sort a list of values apart from a way the system could automatically determine (e.g., alphabetically, chronologically, numerically, etc.) is to create your own definition. Without human intervention or customized rules, there is no way any system would know that "C" should come before "S" (as in "Assigned" and "Accepted", or that "O" should come before "L" as in "Completed" and "Closed").
Since the system knows how to order numbers (e.g., 1,2,3, etc.), it makes sense to create your "rule" (using your CASE statement) to assign each status level to the appropriate "number" in the sequence.
That's what I would do. The only addition I can add is you could do this in the rpd by adding an "order" column to your LOVs in the table and exposing that as a column in the Presentation Layer. Then you can use that order column as the sort. -
A better way to write last_day query
Hi folks,
I am looking for a better way to write a query to find last_day in month but if its sunday or holiday it should move to day before last day.
So for example if 31 is sunday it should go for 30, if 30 is holiday it should move down to 29.
I got this so far but the connect by level is hardcoded to 15. Want to see if there is a better way to get this working:
select max(datum)
from ( select last_day(trunc(sysdate)) - level + 1 as datum
from dual
connect by level < 15)
where to_char(datum, 'day') != 'sunday'
and to_char(datum, 'DDMM') not in
('3012')Best regards,
IgorLike this
select to_char(last_day_month, 'Day') day_is,
last_day_month,
last_day_month - case when to_char(last_day_month, 'fmday') = 'sunday' then 1
when to_char(last_day_month, 'ddmm' ) = '3012' then 1
else 0
end last_business_day_month
from (
select last_day(add_months(trunc(sysdate, 'year'), level-1)) last_day_month
from dual
connect by level <= 12
DAY_IS LAST_DAY_MONTH LAST_BUSINESS_DAY_MONTH
Tuesday 31-JAN-12 31-JAN-12
Wednesday 29-FEB-12 29-FEB-12
Saturday 31-MAR-12 31-MAR-12
Monday 30-APR-12 30-APR-12
Thursday 31-MAY-12 31-MAY-12
Saturday 30-JUN-12 30-JUN-12
Tuesday 31-JUL-12 31-JUL-12
Friday 31-AUG-12 31-AUG-12
Sunday 30-SEP-12 29-SEP-12
Wednesday 31-OCT-12 31-OCT-12
Friday 30-NOV-12 30-NOV-12
Monday 31-DEC-12 31-DEC-12 -
A better way to edit content within a slideshow widget?
Is there a better way to edit the content of slideshow widgets? I understand the way to see the content of a slideshow and edit it is by viewing thumbnails, but this is a very clunky way to be dealing with a lot of content! It would be super cool to be able to link an entire folder to a slideshow widget and have it update when changes are made in that folder. that way designers could organize their files in finder or bridge and then simply update the slideshow link - i would love that!
I was afraid of that...
I don't use lightroom or Photoshop. I used to be a Photoshop user until the cost became so prohibitive. I have since switched to using GIMP as my eternal editor, it's native files are .xcf (musch like the Photoshop .PSD) but Aperture doesn't support .xcf files and I doubt they ever will since GIMP is a free open source tool, rather than a commercial product.
I have been playing with 3.01 now for a few days and finding that the heal tool and burn and dodge tools seem to be improved. Even though in GIMP they were destructive to the original RAW file those items were noticeably better in the external editor.
Also, any extreme editing still needs to be done outside of Aperture, so I will take a Catapult or just keep my current workflow.... -
What is the best way to organize photos? iPhoto or Aperture?
I am a mom taking tons of photos of my young children. On my old PC I used to organize everything within "My Pictures" by Month & Year (May 2008). I am a very organized, linear person and don't like to change the way I do things midstream so I am having a hard time figuring out how to organize our family photos now that I have switched to a Mac with iPhoto and Aperture. In the future I hope to learn about Aperture's professional tools (which as a mom & not a professional photographer I currently do not use). I would love to take photography classes at a local community college someday...
My questions are as follows:
1) What is the better way for ME to store our photos? Should I be uploading to iPhoto or Aperture? I basically want all of my "master photo images" in the same location in an organized fashion. I am hoping to do this without clogging up my computer. At this point I am thinking at the end of each year I will burn the year's photos to a disk for save keeping. But until then...
2) Is the "library" the over-arching place where all photos are stored? In general, I am having a hard time following the hierarchy of where my photos are being stored, how to organize them and how to completely delete bad photos.
3) Can I do everything I can do in iPhoto in Aperture? Obviously I know I can do more but is it as easy to edit/fix up photos?
I have listened to/watched several tutorials on both programs and have read through many other folks' questions/answers but I am still not sure of what to do.
I really appreciate any help/advice anyone is willing to give!
Thanks!I'm not a professional either, just a grandma with a love of digital photography who takes lots of photos. We used to live in a motorhome full time, so we had lots of opportunities to take many photos.
I personally like Aperture better than iPhoto because I like to use some of the NIK software/plugins where I can do the adjusting right in Aperture and don't always have to send the photos to PhotoShop. Also you have a bit more flexibility as to file set ups with Aperture. In iPhoto you don't have as many nesting capabilities. iPhoto is great, but pretty basic.
I had my photos set up as files on the PC, long before I got my first Mac. So I set them up the same way. I'll try to explain
In Finder:
Pictures (in side bar on left in Finder)
Folder - My Photos
2nd Folder - by year
In the year folder I have a folder by date ie: 20000722 (year,month,date) and the photos from that date in there.
Once I got to using Aperture, I have my years set up as "projects" and the dates set up as "Albums". When importing the whole set of photos into Aperture, it was easy. I highlighted the "library", then did a right mouse click and selected "import folders as projects". That imported the photos into Aperture the same way I have them in finder.
Once everything is in Aperture, and you have new photos to add, I make an album under the corresponding year and import.
I do all my photos as referenced and don't duplicate them again, as I have them backed up in a couple of other places.
IMHO you can't back up enough! Don't wait and do it only once a year! Hard drives have a way of crashing and you'll loose all your photos. Use DVD's, thumb drives, ext. hard drives or what ever works for you. But always back up.
When I take my photos off of the memory card, I immediately send a copy to the back up external HD. Once the photos are adjusted etc. I make sure I have a copy elsewhere too. Only then do I erase them off of the memory card. Might be a bit redundant, but I'm not about to loose any of my photos. When we lived in the motorhome we were always aware of the possibility of theft or fire. So I got in the habit of taking some time to reduce the size of the photos and keep them on a thumb drive that I kept out of the RV. If anyone broke in or we had a fire, I'd still have the photos. Maybe not the originals or the bigger size, but we wouldn't loose them either.
If you want more info on non professional filing, send me a PM and I can send you a photo of my file hierarchy . (suemach (at) mac (dot) com)
Allie
Maybe you are looking for
-
I have a Mc g5 with the 10.4.11 operating system. Your site is my home page and it kept bugging me to update to the firefox 4. So I did now when I try to get on it tells me that that "I can not open this application because it is not supported on thi
-
Hp omni 10 windows 8.1 64bit
It is possible to run Windows 8.1 x64 to HP Omni 10 5600eg?????? Anyone tried?????? The prcessor is a Intel Atom Z3770 with x64 technology supported, tablet has 2GB memory so theoretically it should be possible
-
Hi, I am taking over a Crystal Reports XI II installation and i have no prior experience. I am only responsible for the underlying operating system on which the software runs (win 2k3 R2 SP2). Our server's CPU (running on VMware ESX 3.5 U4) has two V
-
Replacing pictures in theme..
Hi all, I have the pictures in themes_11 in themes folder,i want to replace them with new design that i alreat design....now what i have to do to be able to use this template after modification and what changes must be done in order to see the new te
-
Performance: many queries used in dashboard
Hi experts, My dashboard contains more than 30 queries runing on 2 multiproviders. When looking in sm50 it seems as though only 2 queries are run in parallel after pressing the submit button. Moreover the queries that should provide results on the fi