source: trunk/src/org/expeditee/io/Conversion.java@ 919

Last change on this file since 919 was 919, checked in by jts21, 10 years ago

Added license headers to all files, added full GPL3 license file, moved license header generator script to dev/bin/scripts

File size: 19.4 KB
Line 
1/**
2 * Conversion.java
3 * Copyright (C) 2010 New Zealand Digital Library, http://expeditee.org
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19package org.expeditee.io;
20
21import java.awt.Color;
22import java.awt.Font;
23import java.awt.Point;
24import java.lang.reflect.Field;
25import java.lang.reflect.Method;
26import java.util.LinkedList;
27import java.util.List;
28import java.util.StringTokenizer;
29
30import org.expeditee.actions.Actions;
31import org.expeditee.items.Item;
32import org.expeditee.items.Text;
33
34import com.lowagie.text.FontFactory;
35
36/**
37 * This class provides various methods for converting values to\from Java
38 * objects and Expeditee file values.
39 *
40 * @author jdm18
41 *
42 */
43public class Conversion {
44
45 public static final int RGB_MAX = 255;
46
47 private static final float RGB_CONVERSION_FACTOR = 2.55F;
48
49 /**
50 * Returns the Color corresponding to the given Expeditee color code. For
51 * example: <br>
52 * green4 = 0% red, 40% green, 0% blue.
53 *
54 * @param colorCode
55 * The Expeditee color code to convert
56 * @return The Color object corresponding to the given code
57 */
58 public static Color getColor(String colorCode, Color current) {
59 if (colorCode == null) {
60 return null;
61 }
62 // The if we dont do this then we end up getting black
63 colorCode = colorCode.toLowerCase();
64 if (colorCode.equals("null"))
65 return null;
66
67 // check if its a normal rgb code ie. 100 0 40
68 Color rgb = getRGBColor(colorCode, current);
69 if (rgb != null)
70 return rgb;
71
72 // separate percentage from color (if necessary)
73 String num = "";
74 int last = colorCode.length() - 1;
75
76 char c = colorCode.charAt(last);
77
78 while (Character.isDigit(c)) {
79 num = c + num;
80 if (last <= 0)
81 break;
82
83 c = colorCode.charAt(--last);
84 }
85
86 final float MAX_AMOUNT = 10F;
87 float amount = MAX_AMOUNT;
88 if (num.length() > 0)
89 amount = Float.parseFloat(num);
90
91 if (amount > MAX_AMOUNT)
92 amount = MAX_AMOUNT;
93
94 float color[] = { 0, 0, 0 };
95 // Assert.assertTrue(color.length == 3);
96
97 if (colorCode.startsWith("red"))
98 color[0] = amount / MAX_AMOUNT;
99 else if (colorCode.startsWith("green"))
100 color[1] = amount / MAX_AMOUNT;
101 else if (colorCode.startsWith("blue"))
102 color[2] = amount / MAX_AMOUNT;
103 else
104 return null;
105
106 return new Color(color[0], color[1], color[2]);
107 }
108
109 private static Color getRGBColor(String colorCode, Color current) {
110 int color[] = new int[4];
111 // Assert.assertTrue(color.length == 3);
112
113 try {
114 String[] values = colorCode.trim().split("\\s+");
115 // For now no transparency only RGB
116 if (values.length > color.length)
117 return null;
118
119 String r = values.length > 0 ? values[0] : "0";
120 String g = values.length > 1 ? values[1] : "0";
121 String b = values.length > 2 ? values[2] : "0";
122 String a = values.length > 3 ? values[3] : "100";
123
124 int red = (current == null ? 0 : toColorPercent(current.getRed()));
125 int green = (current == null ? 0 : toColorPercent(current.getGreen()));
126 int blue = (current == null ? 0 : toColorPercent(current.getBlue()));
127 int alpha = (current == null ? 0 : toColorPercent(current.getAlpha()));
128
129 color[0] = (Integer) Convert(int.class, r, red);
130 color[1] = (Integer) Convert(int.class, g, green);
131 color[2] = (Integer) Convert(int.class, b, blue);
132 color[3] = (Integer) Convert(int.class, a, alpha);
133
134 for (int i = 0; i < color.length; i++) {
135 color[i] = toRGB(color[i]);
136 }
137 return new Color(color[0], color[1], color[2], color[3]);
138 } catch (Exception e) {
139 return null;
140 }
141 }
142
143 private static Integer toColorPercent(int rgb) {
144 assert (rgb >= 0);
145 assert (rgb <= RGB_MAX);
146
147 int percent = (int) Math.round(rgb / RGB_CONVERSION_FACTOR);
148
149 // Dont need to do the checking below because this method will always be
150 // called with good values
151 // if (percent > PERCENT_MAX)
152 // percent = PERCENT_MAX;
153 // else if (percent < 0)
154 // percent = 0;
155
156 return percent;
157 }
158
159 private static Integer toRGB(int percent) {
160 int rgb = Math.round(percent * RGB_CONVERSION_FACTOR);
161 if (rgb > RGB_MAX)
162 rgb = RGB_MAX;
163 else if (rgb < 0)
164 rgb = 0;
165
166 return rgb;
167 }
168
169 /**
170 * Converts the given Color object to the corresponding Expeditee color code
171 *
172 * @param color
173 * The Color to be turned into Expeditee color code.
174 * @return A String containing the Expeditee color code, NULL if the color
175 * is black.
176 */
177 public static String getExpediteeColorCode(Color color) {
178 if (color == null)
179 return null;
180
181 int r = (int) Math.round((color.getRed() / RGB_CONVERSION_FACTOR));
182 int g = (int) Math.round((color.getGreen() / RGB_CONVERSION_FACTOR));
183 int b = (int) Math.round((color.getBlue() / RGB_CONVERSION_FACTOR));
184 int a = (int) Math.round((color.getAlpha() / RGB_CONVERSION_FACTOR));
185
186 return r + " " + g + " " + b + " " + a;
187 }
188
189 /**
190 * Converts the given Font to a corresponding Expeditee font code.
191 *
192 * @param font
193 * The Font to convert to a code.
194 * @return The Expeditee font code that corresponds to the given Font.
195 */
196 public static String getExpediteeFontCode(Font font) {
197 String fontName = font.getFamily();
198 String code = font.getFamily() + '_';
199
200 for (int i = 0; i < Text.FONT_WHEEL.length; i++) {
201 if (Text.FONT_WHEEL[i].equalsIgnoreCase(fontName)) {
202 code = "" + Text.FONT_CHARS[i];
203 break;
204 }
205 }
206
207 switch (font.getStyle()) {
208 case Font.BOLD:
209 code += "b";
210 break;
211 case Font.PLAIN:
212 code += "r";
213 break;
214 case Font.ITALIC:
215 code += "i";
216 break;
217 default:
218 code += "p";
219 break;
220 }
221
222 code += font.getSize();
223 return code;
224 }
225
226 /**
227 * Converts the given Expeditee font code to a Font object.<br>
228 * For example: <br>
229 * tr16 = times, roman, 16pt
230 *
231 * @param fontCode
232 * The font code to convert to a Font
233 * @return the Font that corresponds to the given font code.
234 */
235 public static Font getFont(String fontCode) {
236 assert (fontCode != null);
237
238 int separator = fontCode.indexOf('_');
239 String code = Text.FONT_WHEEL[0];
240 if (separator > 0) {
241 code = Actions.getCapitalizedFontName(fontCode.substring(0,
242 separator)) + '-';
243 fontCode = fontCode.substring(separator);
244 } else {
245 char c = fontCode.charAt(0);
246 for (int i = 0; i < Text.FONT_CHARS.length; i++) {
247 if (c == Text.FONT_CHARS[i]) {
248 code = Text.FONT_WHEEL[i] + '-';
249 break;
250 }
251 }
252 }
253
254 switch (fontCode.charAt(1)) {
255 case 'r':
256 code += "Plain";
257 break;
258 case 'b':
259 code += "Bold";
260 break;
261 case 'i':
262 code += "Italic";
263 break;
264 case 'p':
265 code += "BoldItalic";
266 break;
267 }
268
269 code += "-";
270
271 Font font = null;
272
273 try {
274 int size = Integer.parseInt(fontCode.substring(2));
275 // double dsize = size * FONT_SCALE;
276 // if (dsize - ((int) dsize) > FONT_ROUNDING)
277 // dsize = Math.ceil(dsize);
278
279 // code += (int) dsize;
280 code += size;
281
282 font = Font.decode(code);
283 } catch (NumberFormatException nfe) {
284 font = Font.decode(fontCode);
285 }
286
287 return font;
288 }
289
290 /**
291 * Returns the number portion (Frame Number) of the given Frame name.
292 *
293 * @param framename
294 * The Frame name to extract the number from
295 * @return The Frame number
296 */
297 public static int getFrameNumber(String framename) {
298 String num = null;
299 // The framename must end in a digit
300 assert (Character.isDigit(framename.charAt(framename.length() - 1)));
301 // And start with a letter
302 assert (Character.isLetter(framename.charAt(0)));
303 // start at the end and find the first non digit char
304 for (int i = framename.length() - 2; i >= 0; i--) {
305 if (!Character.isDigit(framename.charAt(i))) {
306 num = framename.substring(i + 1);
307 break;
308 }
309 }
310 return Integer.parseInt(num);
311 }
312
313 /**
314 * Returns the frameset poriton of the given Frame name (frame number
315 * removed) converted to lower case.
316 *
317 * @param frame
318 * The full name to extract the Frameset name from
319 * @return the name of the Frameset extracted from the given Frame name.
320 */
321 public static String getFramesetName(String frame) {
322 return getFramesetName(frame, true);
323 }
324
325 public static String getFramesetName(String framename,
326 boolean convertToLower) {
327 String set = null;
328 assert (Character.isDigit(framename.charAt(framename.length() - 1)));
329 // And start with a letter
330 assert (Character.isLetter(framename.charAt(0)));
331 // start at the end and find the first non digit char
332 for (int i = framename.length() - 2; i >= 0; i--) {
333 if (!Character.isDigit(framename.charAt(i))) {
334 set = framename.substring(0, i + 1);
335 break;
336 }
337 }
338
339 if (convertToLower)
340 return set.toLowerCase();
341
342 return set;
343 }
344
345 public static Object Convert(Class type, String value) {
346 return Convert(type, value, null);
347 }
348
349 // Will convert from Expeditee color values to RGB...
350 public static Object Convert(Class type, String value, Object orig) {
351 // System.out.println("Orig: " + orig);
352 assert (type != null);
353
354 if (value == null)
355 return null;
356
357 String fullCaseValue = value;
358 value = fullCaseValue.trim().toLowerCase();
359
360 if (type == Font.class) {
361 return getFont(value);
362 }
363
364 if (type.equals(Color.class)) {
365 if (value.length() == 0)
366 return null;
367
368 try {
369 // Try to decode the string as a hex or octal color code
370 return Color.decode(value);
371 } catch (NumberFormatException nfe) {
372 try {
373 // Try to find the field in the Color class with the same name as the given string
374 Field[] fields = java.awt.Color.class.getFields();
375 Field field = null;
376 for (int i = 0; i < fields.length; i++) {
377 if (fields[i].getName().equalsIgnoreCase(value)) {
378 field = fields[i];
379 break;
380 }
381 }
382 return (Color) field.get(null);
383 } catch (Exception e) {
384 return getColor(value, (Color) orig);
385 }
386 }
387 }
388
389 if (type.equals(int.class)) {
390 if (orig instanceof Integer
391 && (value.startsWith("+") || value.startsWith("-"))) {
392 value = value.replace("+", "");
393
394 return ((Integer) orig) + Integer.decode(value);
395 }
396
397 if (value.length() == 0 || value.equals("null"))
398 return Item.DEFAULT_INTEGER;
399
400 return Integer.decode(value);
401 }
402
403 if (type.equals(float.class)) {
404 if (orig instanceof Float
405 && (value.startsWith("+") || value.startsWith("-"))) {
406 value = value.replace("+", "");
407
408 return ((Float) orig) + Float.parseFloat(value);
409 }
410
411 return Float.parseFloat(value);
412 }
413
414 if (type.equals(Float.class)) {
415 if (orig instanceof Float
416 && (value.startsWith("+") || value.startsWith("-"))) {
417 value = value.replace("+", "");
418
419 return ((Float) orig) + Float.parseFloat(value);
420 }
421
422 if (value.length() == 0 || value.equals("null"))
423 return null;
424
425 return Float.parseFloat(value);
426 }
427
428 if (type.equals(Integer.class)) {
429 if (orig instanceof Integer
430 && (value.startsWith("+") || value.startsWith("-"))) {
431 value = value.replace("+", "");
432
433 Integer newValue = ((Integer) orig) + Integer.parseInt(value);
434 if (newValue <= 0)
435 return null;
436 return newValue;
437 }
438
439 if (value.length() == 0 || value.equals("null"))
440 return null;
441
442 return Integer.parseInt(value);
443 }
444
445 if (type.equals(double.class)) {
446 if (orig instanceof Double
447 && (value.startsWith("+") || value.startsWith("-"))) {
448 value = value.replace("+", "");
449
450 return ((Double) orig) + Double.parseDouble(value);
451 }
452
453 return Double.parseDouble(value);
454 }
455
456 if (type.equals(int[].class)) {
457 StringTokenizer st = new StringTokenizer(value, " ");
458 int[] param = new int[st.countTokens()];
459 for (int i = 0; i < param.length; i++) {
460 try {
461 param[i] = Integer.parseInt(st.nextToken());
462 } catch (Exception e) {
463 return null;
464 }
465 }
466
467 return param;
468 }
469
470 if (type.equals(Font.class)) {
471 return Conversion.getFont(value);
472 }
473
474 if (type.equals(boolean.class)) {
475 if (value.equals("t") || value.equals("true")
476 || value.equals("yes") || value.equals("y")
477 || value.equals(""))
478 return true;
479 return false;
480
481 }
482
483 if (type.equals(Point.class)) {
484 Point p = new Point();
485 String xPos = value.substring(0, value.indexOf(" "));
486 String yPos = value.substring(value.indexOf(" ") + 1);
487
488 if (orig == null) {
489 p.x = Integer.parseInt(xPos.trim());
490 p.y = Integer.parseInt(yPos.trim());
491 } else {
492 assert (orig instanceof Point);
493 Point originalPoint = (Point) orig;
494 p.x = (Integer) Convert(int.class, xPos, originalPoint.x);
495 p.y = (Integer) Convert(int.class, yPos, originalPoint.y);
496 }
497 return p;
498 }
499
500 assert (type == String.class);
501 if (value.equals(""))
502 return null;
503 return fullCaseValue;
504 }
505
506 public static Object[] Convert(Method method, String value) {
507 return Convert(method, value, null);
508 }
509
510 /**
511 * Converts parameters for setting an attribute from a string form into an
512 * object array form. The object array can then be passed when invoke the
513 * set method via reflection.
514 *
515 * @param method
516 * a method which sets an attribute
517 * @param value
518 * new value for the attribute
519 * @param current
520 * current value of the attribute
521 * @return
522 */
523 public static Object[] Convert(Method method, String value, Object current) {
524
525 if (method == null) {
526 System.out.println("Error converting null method");
527 return null;
528 }
529
530 String name = method.getName();
531 Class[] types = method.getParameterTypes();
532
533 String fullValue = value;
534 value = value.trim();
535
536 if ((method.getParameterTypes()[0].isEnum()) || (name.matches("setPermission"))) {
537 Method convertString;
538 Object[] objects = new Object[1];
539 try {
540 convertString = method.getParameterTypes()[0].getMethod(
541 "convertString", new Class[] { String.class });
542 objects[0] = convertString.invoke(null, new Object[] { value });
543 } catch (Exception e) {
544 e.printStackTrace();
545 }
546 return objects;
547 }
548
549 if (name.endsWith("Arrow")) {
550 if (value.indexOf(" ") < 0)
551 return null;
552
553 Float length = null;
554 Double ratio = null;
555 Double nib_perc = null;
556
557 if (current == null) {
558 length = getArrowLength(value);
559 ratio = getArrowRatio(value);
560 nib_perc = getArrowNibPerc(value);
561 } else {
562 assert (current instanceof String);
563 float oldLength = getArrowLength(current.toString());
564 double oldRatio = getArrowRatio(current.toString());
565 double oldNibPerc = getArrowNibPerc(current.toString());
566
567 int first_space_pos = value.indexOf(" ");
568 String args23 = value.substring(first_space_pos).trim();
569 int second_space_pos = args23.indexOf(" ");
570
571 if (second_space_pos<0) {
572 // two argument form of arrow data (no nib value)
573 second_space_pos = args23.length();
574 }
575
576 length = (Float) Convert(float.class, value.substring(0, value.indexOf(" ")), oldLength);
577 ratio = (Double) Convert(double.class, args23.substring(0,second_space_pos).trim(), oldRatio);
578
579 if (second_space_pos==args23.length()) {
580 nib_perc = oldNibPerc;
581 }
582 else {
583 nib_perc = (Double) Convert(double.class, args23.substring(second_space_pos).trim(), oldNibPerc);
584 }
585
586 }
587
588 Object[] vals = new Object[3];
589 vals[0] = length;
590 vals[1] = ratio;
591 vals[2] = nib_perc;
592 return vals;
593 }
594
595 if (types.length == 1 && types[0] == List.class) {
596 StringTokenizer st = new StringTokenizer(value, "\n");
597 List<String> list = new LinkedList<String>();
598 while (st.hasMoreTokens())
599 list.add(st.nextToken());
600
601 Object[] vals = new Object[1];
602 vals[0] = list;
603 return vals;
604 }
605
606 assert (types.length == 1);
607
608 Object o[] = new Object[1];
609 o[0] = Convert(types[0], fullValue, current);
610 return o;
611 }
612
613 private static float getArrowLength(String args123) {
614 return Float.parseFloat(args123.substring(0, args123.indexOf(" ")));
615 }
616
617 private static double getArrowRatio(String args123) {
618 int first_space_pos = args123.indexOf(" ");
619 String args23 = args123.substring(first_space_pos).trim();
620 int second_space_pos = args23.indexOf(" ");
621
622 if (second_space_pos<0) {
623 // two argument form of arrow data (no nib value)
624 second_space_pos = args23.length();
625 }
626 return Double.parseDouble(args23.substring(0,second_space_pos).trim());
627 }
628
629 private static double getArrowNibPerc(String args123) {
630 int first_space_pos = args123.indexOf(" ");
631 String args23 = args123.substring(first_space_pos).trim();
632 int second_space_pos = args23.indexOf(" ");
633
634 double nib_perc = Item.DEFAULT_ARROWHEAD_NIB_PERC;
635
636 if (second_space_pos>0) {
637 String nib_perc_str = args23.substring(second_space_pos).trim();
638 nib_perc = Double.parseDouble(nib_perc_str);
639 }
640
641 return nib_perc;
642
643 }
644
645 public static Object ConvertToExpeditee(Method method, Object output) {
646 if (output == null)
647 return null;
648
649 assert (method != null);
650
651 String name = method.getName();
652
653 if (output instanceof List)
654 return output;
655
656 if (name.endsWith("Text")) {
657 List<String> list = new LinkedList<String>();
658 for (String s : output.toString().split("\n")) {
659 list.add(s);
660 }
661 return list;
662 }
663
664 if ((method.getReturnType().isEnum()) || (name.equals("getPermission"))) {
665 try {
666 return output.getClass().getMethod("getCode", new Class[] {})
667 .invoke(output, new Object[] {});
668 } catch (Exception e) {
669 e.printStackTrace();
670 }
671 return null;
672 }
673
674 // strings can be returned immediately
675 if (output instanceof String)
676 return (String) output;
677
678 // For int's... negative numbers signal NULL
679 /*
680 * TODO change so that all items use Integer class... where null,
681 * signals null
682 */
683 if (method.getReturnType().equals(int.class)) {
684 if ((Integer) output >= 0)
685 return output + "";
686 return null;
687 }
688
689 // integers can also(Float) output >= 0 be returned immediately
690 if (output instanceof Integer)
691 return "" + output;
692
693 // floats can also be returned immediately
694 if (output instanceof Float) // && (Float) output >= 0) // Removed checking if >0, as some floats (e.g. letter spacing) can be negative
695 return "" + output;
696
697 // convert fonts
698 if (output instanceof Font)
699 return getExpediteeFontCode((Font) output);
700
701 // convert colors
702 if (output instanceof Color)
703 return getExpediteeColorCode((Color) output);
704
705 // covert points
706 if (output instanceof Point)
707 return ((Point) output).x + " " + ((Point) output).y;
708
709 if (output instanceof Boolean)
710 if ((Boolean) output)
711 return null;
712 else
713 return "F";
714
715 if (output instanceof int[]) {
716 int[] out = (int[]) output;
717 String res = "";
718 for (int i : out)
719 res += i + " ";
720
721 res = res.trim();
722 if (res.length() > 0)
723 return res;
724 }
725 // default
726 return null;
727 }
728
729 public static String getPdfFont(String family) {
730 family = family.toLowerCase();
731 if (family.equals(Text.FONT_WHEEL[0])) {
732 return FontFactory.HELVETICA;
733 } else if (family.equals(Text.FONT_WHEEL[2])) {
734 return FontFactory.TIMES_ROMAN;
735 }
736 return FontFactory.COURIER;
737 }
738
739 public static String getCssColor(Color c) {
740 assert (c != null);
741 return "rgb(" + c.getRed() + "," + c.getGreen() + "," + c.getBlue()
742 + ")";
743 }
744
745 public static String getCssFontFamily(String family) {
746 family = family.toLowerCase();
747 if (family.equals("monospaced") || family.equals("dialog")) {
748 return "courier";
749 } else if (family.equals("sansserif")) {
750 return "sans-serif";
751 } else {
752 return family;
753 }
754 }
755}
Note: See TracBrowser for help on using the repository browser.