       1 /*
       2  * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
       3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       4  *
       5  * This code is free software; you can redistribute it and/or modify it
       6  * under the terms of the GNU General Public License version 2 only, as
       7  * published by the Free Software Foundation.  Oracle designates this
       8  * particular file as subject to the "Classpath" exception as provided
       9  * by Oracle in the LICENSE file that accompanied this code.
      10  *
      11  * This code is distributed in the hope that it will be useful, but WITHOUT
      12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14  * version 2 for more details (a copy is included in the LICENSE file that
      15  * accompanied this code).
      16  *
      17  * You should have received a copy of the GNU General Public License version
      18  * 2 along with this work; if not, write to the Free Software Foundation,
      19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
      20  *
      21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
      22  * or visit www.oracle.com if you need additional information or have any
      23  * questions.
      24  */
      25
      26 package com.sun.javafx.css.converters;
      27
      28 import com.sun.javafx.css.StringStore;
      29 import com.sun.javafx.css.StyleConverterImpl;
      30 import java.io.DataInputStream;
      31 import java.io.DataOutputStream;
      32 import java.io.IOException;
      33
      34 import com.sun.javafx.scene.layout.region.RepeatStructConverter;
      35 import javafx.css.ParsedValue;
      36 import javafx.css.StyleConverter;
      37 import javafx.scene.text.Font;
      38
      39 import java.util.HashMap;
      40 import java.util.Locale;
      41 import java.util.Map;
      42
      43 import com.sun.javafx.Logging;
      44 import sun.util.logging.PlatformLogger;
      45 import sun.util.logging.PlatformLogger.Level;
      46
      47 public final class EnumConverter<E extends Enum<E>> extends StyleConverterImpl<String, E> {
      48
      49     // package for unit testing
      50     final Class<E> enumClass;
      51
      52     public EnumConverter(Class<E> enumClass) {
      53         this.enumClass = enumClass;
      54     }
      55
      56     @Override
      57     public E convert(ParsedValue<String, E> value, Font not_used) {
      58         if (enumClass == null) {
      59             return null;
      60         }
      61         String string = value.getValue();
      62         final int dotPos = string.lastIndexOf('.');
      63         if (dotPos > -1) {
      64             string = string.substring(dotPos + 1);
      65         }
      66         try {
      67             string = string.replace('-', '_');
      68             return Enum.valueOf(enumClass, string.toUpperCase(Locale.ROOT));
      69         } catch (IllegalArgumentException e) {
      70             // may throw another IllegalArgumentException
      71             return Enum.valueOf(enumClass, string);
      72         }
      73     }
      74
      75     @Override
      76     public void writeBinary(DataOutputStream os, StringStore sstore) throws IOException {
      77         super.writeBinary(os,sstore);
      78         String ename = enumClass.getName();
      79         int index = sstore.addString(ename);
      80         os.writeShort(index);
      81     }
      82
      83
      84     public static StyleConverter<?,?> readBinary(DataInputStream is, String[] strings)
      85             throws IOException {
      86
      87         short index = is.readShort();
      88         String ename = 0 <= index && index <= strings.length ? strings[index] : null;
      89
      90         if (ename == null || ename.isEmpty()) return null;
      91
      92         if (converters == null || converters.containsKey(ename) == false) {
      93             StyleConverter<?,?> converter = getInstance(ename);
      94
      95             if (converter == null) {
      96                 final PlatformLogger logger = Logging.getCSSLogger();
      97                 if (logger.isLoggable(Level.SEVERE)) {
      98                     logger.severe("could not deserialize EnumConverter for " + ename);
      99                 }
     100             }
     101
     102             if (converters == null) converters = new HashMap<String,StyleConverter<?,?>>();
     103             converters.put(ename, converter);
     104             return converter;
     105         }
     106         return converters.get(ename);
     107     }
     108
     109     private static Map<String,StyleConverter<?,?>> converters;
     110
     111     // package for unit testing
     112     static public StyleConverter<?,?> getInstance(final String ename) {
     113
     114         StyleConverter<?,?> converter = null;
     115
     116         switch (ename) {
     117         case "com.sun.javafx.cursor.CursorType" :
     118             converter = new EnumConverter<com.sun.javafx.cursor.CursorType>(com.sun.javafx.cursor.CursorType.class);
     119             break;
     120         case "javafx.scene.layout.BackgroundRepeat" :
     121         case "com.sun.javafx.scene.layout.region.Repeat" :
     122             converter = new EnumConverter<javafx.scene.layout.BackgroundRepeat>(javafx.scene.layout.BackgroundRepeat.class);
     123             break;
     124         case "javafx.geometry.HPos" :
     125             converter = new EnumConverter<javafx.geometry.HPos>(javafx.geometry.HPos.class);
     126             break;
     127         case "javafx.geometry.Orientation" :
     128             converter = new EnumConverter<javafx.geometry.Orientation>(javafx.geometry.Orientation.class);
     129             break;
     130         case "javafx.geometry.Pos" :
     131             converter = new EnumConverter<javafx.geometry.Pos>(javafx.geometry.Pos.class);
     132             break;
     133         case "javafx.geometry.Side" :
     134             converter = new EnumConverter<javafx.geometry.Side>(javafx.geometry.Side.class);
     135             break;
     136         case "javafx.geometry.VPos" :
     137             converter = new EnumConverter<javafx.geometry.VPos>(javafx.geometry.VPos.class);
     138             break;
     139         case "javafx.scene.effect.BlendMode" :
     140             converter = new EnumConverter<javafx.scene.effect.BlendMode>(javafx.scene.effect.BlendMode.class);
     141             break;
     142         case "javafx.scene.effect.BlurType" :
     143             converter = new EnumConverter<javafx.scene.effect.BlurType>(javafx.scene.effect.BlurType.class);
     144             break;
     145         case "javafx.scene.paint.CycleMethod" :
     146             converter = new EnumConverter<javafx.scene.paint.CycleMethod>(javafx.scene.paint.CycleMethod.class);
     147             break;
     148         case "javafx.scene.shape.ArcType" :
     149             converter = new EnumConverter<javafx.scene.shape.ArcType>(javafx.scene.shape.ArcType.class);
     150             break;
     151         case "javafx.scene.shape.StrokeLineCap" :
     152             converter = new EnumConverter<javafx.scene.shape.StrokeLineCap>(javafx.scene.shape.StrokeLineCap.class);
     153             break;
     154         case "javafx.scene.shape.StrokeLineJoin" :
     155             converter = new EnumConverter<javafx.scene.shape.StrokeLineJoin>(javafx.scene.shape.StrokeLineJoin.class);
     156             break;
     157         case "javafx.scene.shape.StrokeType" :
     158             converter = new EnumConverter<javafx.scene.shape.StrokeType>(javafx.scene.shape.StrokeType.class);
     159             break;
     160         case "javafx.scene.text.FontPosture" :
     161             converter = new EnumConverter<javafx.scene.text.FontPosture>(javafx.scene.text.FontPosture.class);
     162             break;
     163         case "javafx.scene.text.FontSmoothingType" :
     164             converter = new EnumConverter<javafx.scene.text.FontSmoothingType>(javafx.scene.text.FontSmoothingType.class);
     165             break;
     166         case "javafx.scene.text.FontWeight" :
     167             converter = new EnumConverter<javafx.scene.text.FontWeight>(javafx.scene.text.FontWeight.class);
     168             break;
     169         case "javafx.scene.text.TextAlignment" :
     170             converter = new EnumConverter<javafx.scene.text.TextAlignment>(javafx.scene.text.TextAlignment.class);
     171             break;
     172
     173         default :
     174             //
     175             // Enum types that are not in the javafx-ui-common source tree.
     176             //
     177             // Because the parser doesn't explicitly know about these enums
     178             // outside of the javafx-ui-common package, I don't expect these
     179             // EnumConverters to have been persisted. For example, the
     180             // -fx-text-overrun and -fx-content-display properties, will yield
     181             // a ParsedValue<String,String> with a null converter.
     182             //
     183             // If assertions are disabled, then null is returned. The StyleHelper
     184             // code will use the StyleableProperty's converter in this case.
     185             //
     186             assert false : "EnumConverter<"+ ename + "> not expected";
     187
     188             final PlatformLogger logger = Logging.getCSSLogger();
     189             if (logger.isLoggable(Level.SEVERE)) {
     190                 logger.severe("EnumConverter : converter Class is null for : "+ename);
     191             }
     192             break;
     193         }
     194
     195         return converter;
     196     }
     197
     198
     199     @Override
     200     public boolean equals(Object other) {
     201         if (other == this) return true;
     202         if (other == null || !(other instanceof EnumConverter)) return false;
     203         return (enumClass.equals(((EnumConverter)other).enumClass));
     204     }
     205
     206     @Override
     207     public int hashCode() {
     208         return enumClass.hashCode();
     209     }
     210
     211     @Override
     212     public String toString() {
     213         return "EnumConveter[" + enumClass.getName() + "]";
     214     }
     215 }