Beispiel #1
0
/**
 * This class offers advanced configurations capabilities, allowing to provide various categories
 * for configuration variables.
 */
public class Configuration {
  private static boolean[] configBlocks = new boolean[Block.blocksList.length];
  private static boolean[] configItems = new boolean[Item.itemsList.length];
  private static final int ITEM_SHIFT = 256;

  public static final String CATEGORY_GENERAL = "general";
  public static final String CATEGORY_BLOCK = "block";
  public static final String CATEGORY_ITEM = "item";
  public static final String ALLOWED_CHARS = "._-";
  public static final String DEFAULT_ENCODING = "UTF-8";
  private static final CharMatcher allowedProperties =
      CharMatcher.JAVA_LETTER_OR_DIGIT.or(CharMatcher.anyOf(ALLOWED_CHARS));

  File file;

  public Map<String, Map<String, Property>> categories =
      new TreeMap<String, Map<String, Property>>();

  // TO-DO 1.4 - Remove these, categories are dynamically added when needed, so no need to add
  // default categories.
  @Deprecated public TreeMap<String, Property> blockProperties = new TreeMap<String, Property>();
  @Deprecated public TreeMap<String, Property> itemProperties = new TreeMap<String, Property>();
  @Deprecated public TreeMap<String, Property> generalProperties = new TreeMap<String, Property>();
  private Map<String, String> customCategoryComments = Maps.newHashMap();
  private boolean caseSensitiveCustomCategories;
  public String defaultEncoding = DEFAULT_ENCODING;

  static {
    Arrays.fill(configBlocks, false);
    Arrays.fill(configItems, false);
  }

  /** Create a configuration file for the file given in parameter. */
  public Configuration(File file) {
    this.file = file;
    // TO-DO 1.4 - Remove these, categories are dynamically added when needed, so no need to add
    // default categories.
    categories.put(CATEGORY_GENERAL, generalProperties);
    categories.put(CATEGORY_BLOCK, blockProperties);
    categories.put(CATEGORY_ITEM, itemProperties);
  }

  public Configuration(File file, boolean caseSensitiveCustomCategories) {
    this(file);
    this.caseSensitiveCustomCategories = caseSensitiveCustomCategories;
  }

  /**
   * Gets or create a block id property. If the block id property key is already in the
   * configuration, then it will be used. Otherwise, defaultId will be used, except if already
   * taken, in which case this will try to determine a free default id.
   */
  public Property getBlock(String key, int defaultID) {
    return getBlock(CATEGORY_BLOCK, key, defaultID);
  }

  public Property getBlock(String category, String key, int defaultID) {
    Property prop = get(category, key, -1);

    if (prop.getInt() != -1) {
      configBlocks[prop.getInt()] = true;
      return prop;
    } else {
      if (Block.blocksList[defaultID] == null && !configBlocks[defaultID]) {
        prop.value = Integer.toString(defaultID);
        configBlocks[defaultID] = true;
        return prop;
      } else {
        for (int j = configBlocks.length - 1; j > 0; j--) {
          if (Block.blocksList[j] == null && !configBlocks[j]) {
            prop.value = Integer.toString(j);
            configBlocks[j] = true;
            return prop;
          }
        }

        throw new RuntimeException("No more block ids available for " + key);
      }
    }
  }

  public Property getItem(String key, int defaultID) {
    return getItem(CATEGORY_ITEM, key, defaultID);
  }

  public Property getItem(String category, String key, int defaultID) {
    Property prop = get(category, key, -1);
    int defaultShift = defaultID + ITEM_SHIFT;

    if (prop.getInt() != -1) {
      configItems[prop.getInt() + ITEM_SHIFT] = true;
      return prop;
    } else {
      if (Item.itemsList[defaultShift] == null
          && !configItems[defaultShift]
          && defaultShift > Block.blocksList.length) {
        prop.value = Integer.toString(defaultID);
        configItems[defaultShift] = true;
        return prop;
      } else {
        for (int x = configItems.length - 1; x >= ITEM_SHIFT; x--) {
          if (Item.itemsList[x] == null && !configItems[x]) {
            prop.value = Integer.toString(x - ITEM_SHIFT);
            configItems[x] = true;
            return prop;
          }
        }

        throw new RuntimeException("No more item ids available for " + key);
      }
    }
  }

  public Property get(String category, String key, int defaultValue) {
    Property prop = get(category, key, Integer.toString(defaultValue), INTEGER);
    if (!prop.isIntValue()) {
      prop.value = Integer.toString(defaultValue);
    }
    return prop;
  }

  public Property get(String category, String key, boolean defaultValue) {
    Property prop = get(category, key, Boolean.toString(defaultValue), BOOLEAN);
    if (!prop.isBooleanValue()) {
      prop.value = Boolean.toString(defaultValue);
    }
    return prop;
  }

  public Property get(String category, String key, String defaultValue) {
    return get(category, key, defaultValue, STRING);
  }

  public Property get(String category, String key, String defaultValue, Property.Type type) {
    if (!caseSensitiveCustomCategories) {
      category = category.toLowerCase(Locale.ENGLISH);
    }

    Map<String, Property> source = categories.get(category);

    if (source == null) {
      source = new TreeMap<String, Property>();
      categories.put(category, source);
    }

    if (source.containsKey(key)) {
      return source.get(key);
    } else if (defaultValue != null) {
      Property prop = new Property(key, defaultValue, type);
      source.put(key, prop);
      return prop;
    } else {
      return null;
    }
  }

  public boolean hasCategory(String category) {
    return categories.get(category) != null;
  }

  public boolean hasKey(String category, String key) {
    Map<String, Property> cat = categories.get(category);
    return cat != null && cat.get(key) != null;
  }

  public void load() {
    BufferedReader buffer = null;
    try {
      if (file.getParentFile() != null) {
        file.getParentFile().mkdirs();
      }

      if (!file.exists() && !file.createNewFile()) {
        return;
      }

      if (file.canRead()) {
        UnicodeInputStreamReader input =
            new UnicodeInputStreamReader(new FileInputStream(file), defaultEncoding);
        defaultEncoding = input.getEncoding();
        buffer = new BufferedReader(input);

        String line;
        Map<String, Property> currentMap = null;

        while (true) {
          line = buffer.readLine();

          if (line == null) {
            break;
          }

          int nameStart = -1, nameEnd = -1;
          boolean skip = false;
          boolean quoted = false;
          for (int i = 0; i < line.length() && !skip; ++i) {
            if (Character.isLetterOrDigit(line.charAt(i))
                || ALLOWED_CHARS.indexOf(line.charAt(i)) != -1
                || (quoted && line.charAt(i) != '"')) {
              if (nameStart == -1) {
                nameStart = i;
              }

              nameEnd = i;
            } else if (Character.isWhitespace(line.charAt(i))) {
              // ignore space charaters
            } else {
              switch (line.charAt(i)) {
                case '#':
                  skip = true;
                  continue;

                case '"':
                  if (quoted) {
                    quoted = false;
                  }
                  if (!quoted && nameStart == -1) {
                    quoted = true;
                  }
                  break;

                case '{':
                  String scopeName = line.substring(nameStart, nameEnd + 1);

                  currentMap = categories.get(scopeName);
                  if (currentMap == null) {
                    currentMap = new TreeMap<String, Property>();
                    categories.put(scopeName, currentMap);
                  }

                  break;

                case '}':
                  currentMap = null;
                  break;

                case '=':
                  String propertyName = line.substring(nameStart, nameEnd + 1);

                  if (currentMap == null) {
                    throw new RuntimeException("property " + propertyName + " has no scope");
                  }

                  Property prop = new Property();
                  prop.setName(propertyName);
                  prop.value = line.substring(i + 1);
                  i = line.length();

                  currentMap.put(propertyName, prop);

                  break;

                default:
                  throw new RuntimeException("unknown character " + line.charAt(i));
              }
            }
          }
          if (quoted) {
            throw new RuntimeException("unmatched quote");
          }
        }
      }
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      if (buffer != null) {
        try {
          buffer.close();
        } catch (IOException e) {
        }
      }
    }
  }

  public void save() {
    try {
      if (file.getParentFile() != null) {
        file.getParentFile().mkdirs();
      }

      if (!file.exists() && !file.createNewFile()) {
        return;
      }

      if (file.canWrite()) {
        FileOutputStream fos = new FileOutputStream(file);
        BufferedWriter buffer = new BufferedWriter(new OutputStreamWriter(fos, defaultEncoding));

        buffer.write("# Configuration file\r\n");
        buffer.write("# Generated on " + DateFormat.getInstance().format(new Date()) + "\r\n");
        buffer.write("\r\n");

        for (Map.Entry<String, Map<String, Property>> category : categories.entrySet()) {
          buffer.write("####################\r\n");
          buffer.write("# " + category.getKey() + " \r\n");
          if (customCategoryComments.containsKey(category.getKey())) {
            buffer.write("#===================\r\n");
            String comment = customCategoryComments.get(category.getKey());
            Splitter splitter = Splitter.onPattern("\r?\n");
            for (String commentLine : splitter.split(comment)) {
              buffer.write("# ");
              buffer.write(commentLine + "\r\n");
            }
          }
          buffer.write("####################\r\n\r\n");

          String catKey = category.getKey();
          if (!allowedProperties.matchesAllOf(catKey)) {
            catKey = '"' + catKey + '"';
          }
          buffer.write(catKey + " {\r\n");
          writeProperties(buffer, category.getValue().values());
          buffer.write("}\r\n\r\n");
        }

        buffer.close();
        fos.close();
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  public void addCustomCategoryComment(String category, String comment) {
    if (!caseSensitiveCustomCategories) category = category.toLowerCase(Locale.ENGLISH);
    customCategoryComments.put(category, comment);
  }

  private void writeProperties(BufferedWriter buffer, Collection<Property> props)
      throws IOException {
    for (Property property : props) {
      if (property.comment != null) {
        Splitter splitter = Splitter.onPattern("\r?\n");
        for (String commentLine : splitter.split(property.comment)) {
          buffer.write("   # " + commentLine + "\r\n");
        }
      }
      String propName = property.getName();
      if (!allowedProperties.matchesAllOf(propName)) {
        propName = '"' + propName + '"';
      }
      buffer.write("   " + propName + "=" + property.value);
      buffer.write("\r\n");
    }
  }

  // =====================Deprecated stuff, remove in
  // 1.4=============================================
  @Deprecated
  public Property getOrCreateIntProperty(String key, String category, int defaultValue) {
    return get(category, key, defaultValue);
  }

  @Deprecated
  public Property getOrCreateProperty(String key, String category, String defaultValue) {
    return get(category, key, defaultValue);
  }

  @Deprecated
  public Property getOrCreateBooleanProperty(String key, String category, boolean defaultValue) {
    return get(category, key, defaultValue);
  }

  @Deprecated
  public Property getOrCreateBlockIdProperty(String key, int defaultID) {
    return getBlock(CATEGORY_BLOCK, key, defaultID);
  }
  // ======================End deprecated
  // stuff=======================================================

  public static class UnicodeInputStreamReader extends Reader {
    private final InputStreamReader input;
    private final String defaultEnc;

    public UnicodeInputStreamReader(InputStream source, String encoding) throws IOException {
      defaultEnc = encoding;
      String enc = encoding;
      byte[] data = new byte[4];

      PushbackInputStream pbStream = new PushbackInputStream(source, data.length);
      int read = pbStream.read(data, 0, data.length);
      int size = 0;

      int bom16 = (data[0] & 0xFF) << 8 | (data[1] & 0xFF);
      int bom24 = bom16 << 8 | (data[2] & 0xFF);
      int bom32 = bom24 << 8 | (data[3] & 0xFF);

      if (bom24 == 0xEFBBBF) {
        enc = "UTF-8";
        size = 3;
      } else if (bom16 == 0xFEFF) {
        enc = "UTF-16BE";
        size = 2;
      } else if (bom16 == 0xFFFE) {
        enc = "UTF-16LE";
        size = 2;
      } else if (bom32 == 0x0000FEFF) {
        enc = "UTF-32BE";
        size = 4;
      } else if (bom32 == 0xFFFE0000) // This will never happen as it'll be caught by UTF-16LE,
      { // but if anyone ever runs across a 32LE file, i'd like to disect it.
        enc = "UTF-32LE";
        size = 4;
      }

      if (size < read) {
        pbStream.unread(data, size, read - size);
      }

      this.input = new InputStreamReader(pbStream, enc);
    }

    public String getEncoding() {
      return input.getEncoding();
    }

    @Override
    public int read(char[] cbuf, int off, int len) throws IOException {
      return input.read(cbuf, off, len);
    }

    @Override
    public void close() throws IOException {
      input.close();
    }
  }
}
Beispiel #2
0
  public void setDetails() {
    StringBuilder html = new StringBuilder("<html>");
    String name =
        CaseFormat.LOWER_CAMEL.to(
            CaseFormat.UPPER_CAMEL, Optional.fromNullable(ifs.getName()).or(IFS.UNTITLED));
    String words = CharMatcher.JAVA_LETTER_OR_DIGIT.negate().replaceFrom(name, ' ');
    html.append("<a name=\"top\"></a>")
        .append(String.format("<h1 id=\"title\">IFS %s</h1>", words));

    if (ifs.isEmpty()) {
      html.append("<h2>Empty</h2>");
    } else {
      int i = 0;
      int columns = (int) Math.floor((float) getWidth() / 350f);
      html.append("<table>");
      for (Transform t : Ordering.from(IFS.IDENTITY).immutableSortedCopy(ifs)) {
        if (i % columns == 0 && i != 0) html.append("</tr>");
        if (i % columns == 0) html.append("<tr>");
        html.append("<td>").append("<table class=\"ifs\" width=\"250px\">");

        double[] matrix = new double[6];
        t.getTransform().getMatrix(matrix);

        Color c = Color.WHITE;
        if (controller.isColour()) {
          if (controller.hasPalette()) {
            c = controller.getColours().get(i % controller.getPaletteSize());
          } else {
            c = Color.getHSBColor((float) i / (float) ifs.size(), 0.8f, 0.8f);
          }
        }

        String transform =
            String.format(
                "<tr class=\"transform\">"
                    + "<td class=\"id\">%02d</td>"
                    + "<td class=\"bracketl\" rowspan=\"2\">&nbsp;</td>"
                    + "<td class=\"matrixr1\" align=\"right\">%.3f</td>"
                    + "<td class=\"matrixr1\" align=\"right\">%.3f</td>"
                    + "<td class=\"matrixr1\" align=\"right\">%.3f</td>"
                    + "<td class=\"bracketr\" rowspan=\"2\">&nbsp;</td>"
                    + "</tr>"
                    + "<tr class=\"transform\">"
                    + "<td class=\"info\">%.1f%%"
                    + "<div style=\"width: 15px; height: 10px; border: 1px solid %s; "
                    + "background: #%02x%02x%02x; padding: 0; margin: 0;\">&nbsp;</div>"
                    + "</td>"
                    + "<td class=\"matrixr2\" align=\"right\">%.3f</td>"
                    + "<td class=\"matrixr2\" align=\"right\">%.3f</td>"
                    + "<td class=\"matrixr2\" align=\"right\">%.3f</td>"
                    + "</tr>"
                    + "<tr class=\"space\"><td colspan=\"6\">&nbsp;</td></tr>",
                t.getId(),
                matrix[0],
                matrix[1],
                matrix[2],
                100d * t.getDeterminant() / ifs.getWeight(),
                controller.isColour() ? "black" : "white",
                c.getRed(),
                c.getGreen(),
                c.getBlue(),
                matrix[3],
                matrix[4],
                matrix[5]);
        html.append(transform).append("</table>").append("</td>");

        i++;
      }
      html.append("</tr>").append("</table>");
    }

    html.append("</html>");
    setText(html.toString());

    repaint();

    scrollToReference("top");
  }