Package flex2.compiler.i18n

Source Code of flex2.compiler.i18n.PropertyText$InvalidClassReference

/*
*
*  Licensed to the Apache Software Foundation (ASF) under one or more
*  contributor license agreements.  See the NOTICE file distributed with
*  this work for additional information regarding copyright ownership.
*  The ASF licenses this file to You under the Apache License, Version 2.0
*  (the "License"); you may not use this file except in compliance with
*  the License.  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*
*/

package flex2.compiler.i18n;

import java.io.IOException;
import java.io.Reader;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import flex2.compiler.Source;
import flex2.compiler.SymbolTable;
import flex2.compiler.common.CompilerConfiguration;
import flex2.compiler.common.MxmlConfiguration;
import flex2.compiler.io.ResourceFile;
import flex2.compiler.mxml.lang.StandardDefs;
import flex2.compiler.mxml.rep.AtEmbed;
import flex2.compiler.util.OrderedProperties;
import flex2.compiler.util.ThreadLocalToolkit;
import flex2.compiler.util.CompilerMessage.CompilerError;

/**
* Value object used to contain the information from an I18N
* .properties file.
*
* @author Gordon Smith
* @author Clement Wong
*/
public class PropertyText extends OrderedProperties
{
    private static final long serialVersionUID = -4748416824610507873L;
    // things that can start a value
    public static final String CLASS_REFERENCE = "ClassReference(";
    public static final String EMBED = "Embed(";

  public PropertyText(CompilerConfiguration configuration, SymbolTable symbolTable,
          Source source, String locale, StandardDefs standardDefs)
  {
    super();
    this.symbolTable = symbolTable;
    this.source = source;
    this.locale = locale;
    imports = new HashSet<String>();
    atEmbeds = new HashMap<String, AtEmbed>();

    imports.add(standardDefs.CLASS_RESOURCEBUNDLE_DOT);

    int version = configuration.getCompatibilityVersion();
    flex2Compatible = version < MxmlConfiguration.VERSION_3_0;
    }

  private boolean flex2Compatible;
  private SymbolTable symbolTable;
  private Source source;
  private String locale;

    /**
     * If a ClassReference("foo.bar") directive is encountered
     * as a resource value in a .properties file,
     * then "foo.bar" is added to this Set via addImport().
     * When the ResourceBundle subclass is autogenerated,
     * this set of classes to be imported is used
   * to autogenerate import statements like
     *   import "foo.bar";
     */
    Set<String> imports;

    /**
     * If an Embed(...) directive is encountered
     * as a resource value in a .properties file,
     * then an AtEmbed object is added to this Map
     * via addAtEmbed().
     * When the ResourceBundle subclass is autogenerated,
     * this Map is used to autogenerated embedded class
     * declarations like
     *   [Embed(...)]
     *   private static var foo_class:Class;
     */
    Map<String, AtEmbed> atEmbeds;

    public void load(Reader reader) throws IOException
    {
      super.load(reader);
     
      for (Iterator i = keySet().iterator(); i.hasNext(); )
      {
        String key = (String) i.next(), value = getProperty(key);
        Object valueObject;
       
            if (value.startsWith(CLASS_REFERENCE))
            {
                valueObject = processClassReference(key, value);
            }
            else if (value.startsWith(EMBED))
            {
                valueObject = processEmbed(key, value);
            }
            else
            {
              valueObject = value;
            }
           
            if (valueObject != null)
            {
              put(key, valueObject);
            }
      }
    }
   
    /*
     * In Java .properties files, an equal sign, a colon,
     * a space, or a tab can be used to separate the key and value.
     * The getTerminators() method of OrderedProperties
     * returns all of these in order to act like Java.
     * However, Flex 2 supported only '=', while Flex 3 works like Java.
     * This override implements that compatibility logic.
     */
    protected String getTerminators()
    {
      return flex2Compatible ? "=" : super.getTerminators();
    }
   
    /*
     * In Java .properties files, no "bad" characters
     * are removed from the key or value.
     * The removeBadChars() method of OrderedProperties
     * does nothing in order to act like Java.
     * However, Flex 2 removed double-quotes, carriage returns, and newlines.
     * This was a bad idea, and Flex 3 works like Java.
     * This override implements that compatibility logic.
     */
    protected String removeBadChars(String propLine, String string, boolean isValue)
    {
    if (flex2Compatible)
    {
      string = removeBadChars(propLine, string, "\\n");
      string = removeBadChars(propLine, string, "\\r");
      if (isValue && !string.startsWith(CLASS_REFERENCE) && !string.startsWith(EMBED))
      {
        string = removeBadChars(propLine, string, "\"");
      }
    }
    return string;
    }

  // We remove any \n, \r, " characters.  We don't, however, remove \\n, \\r, \\"
    // This happens only in Flex 2; Flex 3 parses .properties files like Java,
    // except for using UTF-8 encoding.
  private static String removeBadChars(String propLine, String str, String bad)
  {
      int index = str.indexOf(bad);
    boolean ignore = index != 0 && str.regionMatches(index - 1, "\\", 0, 1);

      if(index == -1)
          return str;

      StringBuilder buf = new StringBuilder(str.length());
      int lastIndex = 0;
    boolean errorMessage = false;
      while(index != -1) {
          buf.append(str.substring(lastIndex, index));
        if (ignore)
        {
          buf.append(bad);
        }
        else if (! errorMessage)
        {
          errorMessage = true;
          ThreadLocalToolkit.log(new RemovedFromProperty(bad, propLine));
        }
          lastIndex = index + bad.length();
          index = str.indexOf(bad, lastIndex);
        ignore = index != 0 && str.regionMatches(index - 1, "\\", 0, 1);
      }

      // add in last chunk
      buf.append(str.substring(lastIndex));

      return buf.toString();
  }

    /**
     * Called when we find a resource value which is a ClassReference() directive.
     * Returns a ClassReference object which holds the class parameter.
     * Also adds the class to the i18n compiler's list of imports
     * to be put into the autogenerated resource bundle.
     *
     * The ClassReference() directive is also supported in <mx:Script> blocks and CSS files;
     * this method is similar to processClassReference() in StyleDef.
     */
    private ClassReference processClassReference(String key, String value)
    {
        ClassReference classReference = null;
        int lineNumber = (lines.get(key)).intValue();
       
        String parameter = value.substring(CLASS_REFERENCE.length(), value.length() - 1).trim();
        if ((parameter.charAt(0) == '"') && (parameter.indexOf('"', 1) == parameter.length() - 1))
        {
            parameter = parameter.substring(1, parameter.length() - 1);
            classReference = new ClassReference(parameter, lineNumber);
            imports.add(parameter);
        }
    else if (parameter.equals("null"))
    {
      classReference = new ClassReference(null, lineNumber);
    }
        else
        {
            InvalidClassReference invalidClassReference = new InvalidClassReference();
            invalidClassReference.path = getPropertyFileName();
            invalidClassReference.line = lineNumber;
            ThreadLocalToolkit.log(invalidClassReference);
        }

        return classReference;
    }

    /**
     * Called when we find a resource value which is an Embed() directive.
     * Returns an Embed object which keeps track of the parsed parameters.
     * Also adds it to the compiler...
     *
     * The Embed() directive is also supported in <mx:Script> blocks and CSS files;
     */
  private AtEmbed processEmbed(String key, String value)
  {
        int lineNumber = (lines.get(key)).intValue();
        String propertiesPath = getPropertyFileName();
        AtEmbed atEmbed = AtEmbed.create(symbolTable.perCompileData, source, value,
                                         propertiesPath, lineNumber, "_embed_properties_");

        if (atEmbed != null)
        {
            atEmbeds.put(atEmbed.getPropName(), atEmbed);
        }

        return atEmbed;
    }

  private String getPropertyFileName()
  {
    ResourceFile f = (ResourceFile) source.getBackingFile();
    f.setLocale(locale);
    return f.getNameForReporting();
  }
 
    public static class InvalidClassReference extends CompilerError
    {
        private static final long serialVersionUID = -1168616929938888558L;

        public InvalidClassReference()
        {
        }
    }
}
TOP

Related Classes of flex2.compiler.i18n.PropertyText$InvalidClassReference

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.