Repository: incubator-freemarker
Updated Branches:
  refs/heads/3 ace88bf8b -> 5c98c0ed5


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5c98c0ed/src/test/java/org/apache/freemarker/core/userpkg/HTMLISOTemplateDateFormatFactory.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/freemarker/core/userpkg/HTMLISOTemplateDateFormatFactory.java
 
b/src/test/java/org/apache/freemarker/core/userpkg/HTMLISOTemplateDateFormatFactory.java
new file mode 100644
index 0000000..a46de8c
--- /dev/null
+++ 
b/src/test/java/org/apache/freemarker/core/userpkg/HTMLISOTemplateDateFormatFactory.java
@@ -0,0 +1,114 @@
+/*
+ * 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 org.apache.freemarker.core.userpkg;
+
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import org.apache.freemarker.core.Environment;
+import org.apache.freemarker.core.InvalidFormatParametersException;
+import org.apache.freemarker.core.TemplateDateFormat;
+import org.apache.freemarker.core.TemplateDateFormatFactory;
+import org.apache.freemarker.core.TemplateFormatUtil;
+import org.apache.freemarker.core.TemplateValueFormatException;
+import org.apache.freemarker.core.UnformattableValueException;
+import 
org.apache.freemarker.core.UnknownDateTypeFormattingUnsupportedException;
+import org.apache.freemarker.core.UnparsableValueException;
+import org.apache.freemarker.core.model.TemplateDateModel;
+import org.apache.freemarker.core.model.TemplateModelException;
+import org.apache.freemarker.core.outputformat.impl.HTMLOutputFormat;
+import org.apache.freemarker.core.util._DateUtil;
+import org.apache.freemarker.core.util._DateUtil.CalendarFieldsToDateConverter;
+import org.apache.freemarker.core.util._DateUtil.DateParseException;
+
+public class HTMLISOTemplateDateFormatFactory extends 
TemplateDateFormatFactory {
+
+    public static final HTMLISOTemplateDateFormatFactory INSTANCE = new 
HTMLISOTemplateDateFormatFactory();
+    
+    private HTMLISOTemplateDateFormatFactory() {
+        // Defined to decrease visibility
+    }
+    
+    @Override
+    public TemplateDateFormat get(String params, int dateType, Locale locale, 
TimeZone timeZone, boolean zonelessInput,
+            Environment env) throws 
UnknownDateTypeFormattingUnsupportedException, InvalidFormatParametersException 
{
+        TemplateFormatUtil.checkHasNoParameters(params);
+        return HTMLISOTemplateDateFormat.INSTANCE;
+    }
+
+    private static class HTMLISOTemplateDateFormat extends TemplateDateFormat {
+
+        private static final HTMLISOTemplateDateFormat INSTANCE = new 
HTMLISOTemplateDateFormat();
+
+        private _DateUtil.TrivialDateToISO8601CalendarFactory calendarFactory;
+
+        private CalendarFieldsToDateConverter calToDateConverter;
+        
+        private HTMLISOTemplateDateFormat() { }
+        
+        @Override
+        public String formatToPlainText(TemplateDateModel dateModel)
+                throws UnformattableValueException, TemplateModelException {
+            if (calendarFactory == null) {
+                calendarFactory = new 
_DateUtil.TrivialDateToISO8601CalendarFactory();
+            }
+            return _DateUtil.dateToISO8601String(
+                    TemplateFormatUtil.getNonNullDate(dateModel),
+                    true, true, true, _DateUtil.ACCURACY_SECONDS, 
_DateUtil.UTC,
+                    calendarFactory);
+        }
+
+        @Override
+        public boolean isLocaleBound() {
+            return false;
+        }
+
+        @Override
+        public boolean isTimeZoneBound() {
+            return false;
+        }
+
+        @Override
+        public Date parse(String s, int dateType) throws 
UnparsableValueException {
+            try {
+                if (calToDateConverter == null) {
+                    calToDateConverter = new 
_DateUtil.TrivialCalendarFieldsToDateConverter();
+                }
+                return _DateUtil.parseISO8601DateTime(s, _DateUtil.UTC, 
calToDateConverter);
+            } catch (DateParseException e) {
+                throw new UnparsableValueException("Malformed ISO date-time", 
e);
+            }
+        }
+
+        @Override
+        public Object format(TemplateDateModel dateModel) throws 
TemplateValueFormatException, TemplateModelException {
+            return HTMLOutputFormat.INSTANCE.fromMarkup(
+                    formatToPlainText(dateModel).replace("T", "<span 
class='T'>T</span>"));
+        }
+
+        @Override
+        public String getDescription() {
+            return "ISO UTC HTML";
+        }
+        
+    }
+
+}
+ 
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5c98c0ed/src/test/java/org/apache/freemarker/core/userpkg/HexTemplateNumberFormatFactory.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/freemarker/core/userpkg/HexTemplateNumberFormatFactory.java
 
b/src/test/java/org/apache/freemarker/core/userpkg/HexTemplateNumberFormatFactory.java
new file mode 100644
index 0000000..06bc6cb
--- /dev/null
+++ 
b/src/test/java/org/apache/freemarker/core/userpkg/HexTemplateNumberFormatFactory.java
@@ -0,0 +1,77 @@
+/*
+ * 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 org.apache.freemarker.core.userpkg;
+
+import java.util.Locale;
+
+import org.apache.freemarker.core.Environment;
+import org.apache.freemarker.core.InvalidFormatParametersException;
+import org.apache.freemarker.core.TemplateFormatUtil;
+import org.apache.freemarker.core.TemplateNumberFormat;
+import org.apache.freemarker.core.TemplateNumberFormatFactory;
+import org.apache.freemarker.core.UnformattableValueException;
+import org.apache.freemarker.core.model.TemplateModelException;
+import org.apache.freemarker.core.model.TemplateNumberModel;
+import org.apache.freemarker.core.util._NumberUtil;
+
+public class HexTemplateNumberFormatFactory extends 
TemplateNumberFormatFactory {
+
+    public static final HexTemplateNumberFormatFactory INSTANCE = new 
HexTemplateNumberFormatFactory();
+    
+    private HexTemplateNumberFormatFactory() {
+        // Defined to decrease visibility
+    }
+    
+    @Override
+    public TemplateNumberFormat get(String params, Locale locale, Environment 
env)
+            throws InvalidFormatParametersException {
+        TemplateFormatUtil.checkHasNoParameters(params);
+        return HexTemplateNumberFormat.INSTANCE;
+    }
+
+    private static class HexTemplateNumberFormat extends TemplateNumberFormat {
+
+        private static final HexTemplateNumberFormat INSTANCE = new 
HexTemplateNumberFormat();
+        
+        private HexTemplateNumberFormat() { }
+        
+        @Override
+        public String formatToPlainText(TemplateNumberModel numberModel)
+                throws UnformattableValueException, TemplateModelException {
+            Number n = TemplateFormatUtil.getNonNullNumber(numberModel);
+            try {
+                return Integer.toHexString(_NumberUtil.toIntExact(n));
+            } catch (ArithmeticException e) {
+                throw new UnformattableValueException(n + " doesn't fit into 
an int");
+            }
+        }
+
+        @Override
+        public boolean isLocaleBound() {
+            return false;
+        }
+
+        @Override
+        public String getDescription() {
+            return "hexadecimal int";
+        }
+        
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5c98c0ed/src/test/java/org/apache/freemarker/core/userpkg/LocAndTZSensitiveTemplateDateFormatFactory.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/freemarker/core/userpkg/LocAndTZSensitiveTemplateDateFormatFactory.java
 
b/src/test/java/org/apache/freemarker/core/userpkg/LocAndTZSensitiveTemplateDateFormatFactory.java
new file mode 100644
index 0000000..fa8fbf7
--- /dev/null
+++ 
b/src/test/java/org/apache/freemarker/core/userpkg/LocAndTZSensitiveTemplateDateFormatFactory.java
@@ -0,0 +1,97 @@
+/*
+ * 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 org.apache.freemarker.core.userpkg;
+
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import org.apache.freemarker.core.Environment;
+import org.apache.freemarker.core.InvalidFormatParametersException;
+import org.apache.freemarker.core.TemplateDateFormat;
+import org.apache.freemarker.core.TemplateDateFormatFactory;
+import org.apache.freemarker.core.TemplateFormatUtil;
+import org.apache.freemarker.core.UnformattableValueException;
+import 
org.apache.freemarker.core.UnknownDateTypeFormattingUnsupportedException;
+import org.apache.freemarker.core.UnparsableValueException;
+import org.apache.freemarker.core.model.TemplateDateModel;
+import org.apache.freemarker.core.model.TemplateModelException;
+
+public class LocAndTZSensitiveTemplateDateFormatFactory extends 
TemplateDateFormatFactory {
+
+    public static final LocAndTZSensitiveTemplateDateFormatFactory INSTANCE = 
new LocAndTZSensitiveTemplateDateFormatFactory();
+    
+    private LocAndTZSensitiveTemplateDateFormatFactory() {
+        // Defined to decrease visibility
+    }
+    
+    @Override
+    public TemplateDateFormat get(String params, int dateType, Locale locale, 
TimeZone timeZone, boolean zonelessInput,
+            Environment env) throws 
UnknownDateTypeFormattingUnsupportedException, InvalidFormatParametersException 
{
+        TemplateFormatUtil.checkHasNoParameters(params);
+        return new LocAndTZSensitiveTemplateDateFormat(locale, timeZone);
+    }
+
+    private static class LocAndTZSensitiveTemplateDateFormat extends 
TemplateDateFormat {
+
+        private final Locale locale;
+        private final TimeZone timeZone;
+        
+        public LocAndTZSensitiveTemplateDateFormat(Locale locale, TimeZone 
timeZone) {
+            this.locale = locale;
+            this.timeZone = timeZone;
+        }
+
+        @Override
+        public String formatToPlainText(TemplateDateModel dateModel)
+                throws UnformattableValueException, TemplateModelException {
+            return 
String.valueOf(TemplateFormatUtil.getNonNullDate(dateModel).getTime() + "@" + 
locale + ":" + timeZone.getID());
+        }
+
+        @Override
+        public boolean isLocaleBound() {
+            return true;
+        }
+
+        @Override
+        public boolean isTimeZoneBound() {
+            return true;
+        }
+
+        @Override
+        public Date parse(String s, int dateType) throws 
UnparsableValueException {
+            try {
+                int atIdx = s.indexOf("@");
+                if (atIdx == -1) {
+                    throw new UnparsableValueException("Missing @");
+                }
+                return new Date(Long.parseLong(s.substring(0, atIdx)));
+            } catch (NumberFormatException e) {
+                throw new UnparsableValueException("Malformed long");
+            }
+        }
+
+        @Override
+        public String getDescription() {
+            return "millis since the epoch";
+        }
+        
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5c98c0ed/src/test/java/org/apache/freemarker/core/userpkg/LocaleSensitiveTemplateNumberFormatFactory.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/freemarker/core/userpkg/LocaleSensitiveTemplateNumberFormatFactory.java
 
b/src/test/java/org/apache/freemarker/core/userpkg/LocaleSensitiveTemplateNumberFormatFactory.java
new file mode 100644
index 0000000..7bc23ba
--- /dev/null
+++ 
b/src/test/java/org/apache/freemarker/core/userpkg/LocaleSensitiveTemplateNumberFormatFactory.java
@@ -0,0 +1,78 @@
+/*
+ * 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 org.apache.freemarker.core.userpkg;
+
+import java.util.Locale;
+
+import org.apache.freemarker.core.Environment;
+import org.apache.freemarker.core.InvalidFormatParametersException;
+import org.apache.freemarker.core.TemplateFormatUtil;
+import org.apache.freemarker.core.TemplateNumberFormat;
+import org.apache.freemarker.core.TemplateNumberFormatFactory;
+import org.apache.freemarker.core.UnformattableValueException;
+import org.apache.freemarker.core.model.TemplateModelException;
+import org.apache.freemarker.core.model.TemplateNumberModel;
+
+public class LocaleSensitiveTemplateNumberFormatFactory extends 
TemplateNumberFormatFactory {
+
+    public static final LocaleSensitiveTemplateNumberFormatFactory INSTANCE = 
new LocaleSensitiveTemplateNumberFormatFactory();
+    
+    private LocaleSensitiveTemplateNumberFormatFactory() {
+        // Defined to decrease visibility
+    }
+    
+    @Override
+    public TemplateNumberFormat get(String params, Locale locale, Environment 
env)
+            throws InvalidFormatParametersException {
+        TemplateFormatUtil.checkHasNoParameters(params);
+        return new LocaleSensitiveTemplateNumberFormat(locale);
+    }
+
+    private static class LocaleSensitiveTemplateNumberFormat extends 
TemplateNumberFormat {
+    
+        private final Locale locale;
+        
+        private LocaleSensitiveTemplateNumberFormat(Locale locale) {
+            this.locale = locale;
+        }
+        
+        @Override
+        public String formatToPlainText(TemplateNumberModel numberModel)
+                throws UnformattableValueException, TemplateModelException {
+            Number n = numberModel.getAsNumber();
+            try {
+                return n + "_" + locale;
+            } catch (ArithmeticException e) {
+                throw new UnformattableValueException(n + " doesn't fit into 
an int");
+            }
+        }
+    
+        @Override
+        public boolean isLocaleBound() {
+            return true;
+        }
+    
+        @Override
+        public String getDescription() {
+            return "test locale sensitive";
+        }
+        
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5c98c0ed/src/test/java/org/apache/freemarker/core/userpkg/PackageVisibleAll.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/freemarker/core/userpkg/PackageVisibleAll.java 
b/src/test/java/org/apache/freemarker/core/userpkg/PackageVisibleAll.java
new file mode 100644
index 0000000..06fb94a
--- /dev/null
+++ b/src/test/java/org/apache/freemarker/core/userpkg/PackageVisibleAll.java
@@ -0,0 +1,26 @@
+/*
+ * 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 org.apache.freemarker.core.userpkg;
+
+class PackageVisibleAll {
+    
+    PackageVisibleAll() {}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5c98c0ed/src/test/java/org/apache/freemarker/core/userpkg/PackageVisibleAllWithBuilder.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/freemarker/core/userpkg/PackageVisibleAllWithBuilder.java
 
b/src/test/java/org/apache/freemarker/core/userpkg/PackageVisibleAllWithBuilder.java
new file mode 100644
index 0000000..02691a4
--- /dev/null
+++ 
b/src/test/java/org/apache/freemarker/core/userpkg/PackageVisibleAllWithBuilder.java
@@ -0,0 +1,26 @@
+/*
+ * 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 org.apache.freemarker.core.userpkg;
+
+class PackageVisibleAllWithBuilder {
+
+    PackageVisibleAllWithBuilder() {}
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5c98c0ed/src/test/java/org/apache/freemarker/core/userpkg/PackageVisibleAllWithBuilderBuilder.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/freemarker/core/userpkg/PackageVisibleAllWithBuilderBuilder.java
 
b/src/test/java/org/apache/freemarker/core/userpkg/PackageVisibleAllWithBuilderBuilder.java
new file mode 100644
index 0000000..c9be3ad
--- /dev/null
+++ 
b/src/test/java/org/apache/freemarker/core/userpkg/PackageVisibleAllWithBuilderBuilder.java
@@ -0,0 +1,28 @@
+/*
+ * 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 org.apache.freemarker.core.userpkg;
+
+public class PackageVisibleAllWithBuilderBuilder {
+    
+    public PackageVisibleAllWithBuilder build() {
+        return new PackageVisibleAllWithBuilder();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5c98c0ed/src/test/java/org/apache/freemarker/core/userpkg/PackageVisibleWithPublicConstructor.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/freemarker/core/userpkg/PackageVisibleWithPublicConstructor.java
 
b/src/test/java/org/apache/freemarker/core/userpkg/PackageVisibleWithPublicConstructor.java
new file mode 100644
index 0000000..253489a
--- /dev/null
+++ 
b/src/test/java/org/apache/freemarker/core/userpkg/PackageVisibleWithPublicConstructor.java
@@ -0,0 +1,27 @@
+/*
+ * 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 org.apache.freemarker.core.userpkg;
+
+class PackageVisibleWithPublicConstructor {
+    
+    public PackageVisibleWithPublicConstructor() {
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5c98c0ed/src/test/java/org/apache/freemarker/core/userpkg/PrintfGTemplateNumberFormatFactory.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/freemarker/core/userpkg/PrintfGTemplateNumberFormatFactory.java
 
b/src/test/java/org/apache/freemarker/core/userpkg/PrintfGTemplateNumberFormatFactory.java
new file mode 100644
index 0000000..b81f043
--- /dev/null
+++ 
b/src/test/java/org/apache/freemarker/core/userpkg/PrintfGTemplateNumberFormatFactory.java
@@ -0,0 +1,138 @@
+/*
+ * 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 org.apache.freemarker.core.userpkg;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Locale;
+
+import org.apache.freemarker.core.Environment;
+import org.apache.freemarker.core.InvalidFormatParametersException;
+import org.apache.freemarker.core.TemplateFormatUtil;
+import org.apache.freemarker.core.TemplateNumberFormat;
+import org.apache.freemarker.core.TemplateNumberFormatFactory;
+import org.apache.freemarker.core.UnformattableValueException;
+import org.apache.freemarker.core.model.TemplateModelException;
+import org.apache.freemarker.core.model.TemplateNumberModel;
+import org.apache.freemarker.core.outputformat.impl.HTMLOutputFormat;
+import org.apache.freemarker.core.util._StringUtil;
+
+/**
+ * Formats like {@code %G} in {@code printf}, with the specified number of 
significant digits. Also has special
+ * formatter for HTML output format, where it uses the HTML "sup" element for 
exponents.
+ */
+public class PrintfGTemplateNumberFormatFactory extends 
TemplateNumberFormatFactory {
+
+    public static final PrintfGTemplateNumberFormatFactory INSTANCE = new 
PrintfGTemplateNumberFormatFactory();
+    
+    private PrintfGTemplateNumberFormatFactory() {
+        // Defined to decrease visibility
+    }
+    
+    @Override
+    public TemplateNumberFormat get(String params, Locale locale, Environment 
env)
+            throws InvalidFormatParametersException {
+        Integer significantDigits;
+        if (!params.isEmpty()) {
+            try {
+                significantDigits = Integer.valueOf(params);
+            } catch (NumberFormatException e) {
+                throw new InvalidFormatParametersException(
+                        "The format parameter must be an integer, but was 
(shown quoted) "
+                        + _StringUtil.jQuote(params) + ".");
+            }
+        } else {
+            // Use the default of %G
+            significantDigits = null;
+        }
+        return new PrintfGTemplateNumberFormat(significantDigits, locale);
+    }
+
+    private static class PrintfGTemplateNumberFormat extends 
TemplateNumberFormat {
+        
+        private final Locale locale;
+        private final String printfFormat; 
+
+        private PrintfGTemplateNumberFormat(Integer significantDigits, Locale 
locale) {
+            printfFormat = "%" + (significantDigits != null ? "." + 
significantDigits : "") + "G";
+            this.locale = locale;
+        }
+        
+        @Override
+        public String formatToPlainText(TemplateNumberModel numberModel)
+                throws UnformattableValueException, TemplateModelException {
+            final Number n = TemplateFormatUtil.getNonNullNumber(numberModel);
+            
+            // printf %G only accepts Double, BigDecimal and Float 
+            final Number gCompatibleN;
+            if (n instanceof Double  || n instanceof BigDecimal || n 
instanceof Float) {
+                gCompatibleN = n;
+            } else {
+                if (n instanceof BigInteger) {
+                    gCompatibleN = new BigDecimal((BigInteger) n);             
           
+                } else if (n instanceof Long) {
+                    gCompatibleN = BigDecimal.valueOf(n.longValue());
+                } else {
+                    gCompatibleN = Double.valueOf(n.doubleValue());
+                }
+            }
+            
+            return String.format(locale, printfFormat, gCompatibleN);
+        }
+
+        @Override
+        public Object format(TemplateNumberModel numberModel)
+                throws UnformattableValueException, TemplateModelException {
+            String strResult = formatToPlainText(numberModel);
+            
+            int expIdx = strResult.indexOf('E');
+            if (expIdx == -1) {
+                return strResult;
+            }
+                
+            String expStr = strResult.substring(expIdx + 1);
+            int expSignifNumBegin = 0;
+            while (expSignifNumBegin < expStr.length() && 
isExpSignifNumPrefix(expStr.charAt(expSignifNumBegin))) {
+                expSignifNumBegin++;
+            }
+            
+            return HTMLOutputFormat.INSTANCE.fromMarkup(
+                    strResult.substring(0, expIdx)
+                    + "*10<sup>"
+                    + (expStr.charAt(0) == '-' ? "-" : "") + 
expStr.substring(expSignifNumBegin)
+                    + "</sup>");
+        }
+
+        private boolean isExpSignifNumPrefix(char c) {
+            return c == '+' || c == '-' || c == '0';
+        }
+
+        @Override
+        public boolean isLocaleBound() {
+            return true;
+        }
+
+        @Override
+        public String getDescription() {
+            return "printf " + printfFormat;
+        }
+        
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5c98c0ed/src/test/java/org/apache/freemarker/core/userpkg/PublicAll.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/core/userpkg/PublicAll.java 
b/src/test/java/org/apache/freemarker/core/userpkg/PublicAll.java
new file mode 100644
index 0000000..c10bcfc
--- /dev/null
+++ b/src/test/java/org/apache/freemarker/core/userpkg/PublicAll.java
@@ -0,0 +1,24 @@
+/*
+ * 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 org.apache.freemarker.core.userpkg;
+
+public class PublicAll {
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5c98c0ed/src/test/java/org/apache/freemarker/core/userpkg/PublicWithMixedConstructors.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/freemarker/core/userpkg/PublicWithMixedConstructors.java
 
b/src/test/java/org/apache/freemarker/core/userpkg/PublicWithMixedConstructors.java
new file mode 100644
index 0000000..7bfbee9
--- /dev/null
+++ 
b/src/test/java/org/apache/freemarker/core/userpkg/PublicWithMixedConstructors.java
@@ -0,0 +1,38 @@
+/*
+ * 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 org.apache.freemarker.core.userpkg;
+
+public class PublicWithMixedConstructors {
+    
+    private final String s;
+
+    public PublicWithMixedConstructors(Integer x) {
+        s = "Integer";
+    }
+
+    PublicWithMixedConstructors(int x) {
+        s = "int";
+    }
+
+    public String getS() {
+        return s;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5c98c0ed/src/test/java/org/apache/freemarker/core/userpkg/PublicWithPackageVisibleConstructor.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/freemarker/core/userpkg/PublicWithPackageVisibleConstructor.java
 
b/src/test/java/org/apache/freemarker/core/userpkg/PublicWithPackageVisibleConstructor.java
new file mode 100644
index 0000000..769674d
--- /dev/null
+++ 
b/src/test/java/org/apache/freemarker/core/userpkg/PublicWithPackageVisibleConstructor.java
@@ -0,0 +1,26 @@
+/*
+ * 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 org.apache.freemarker.core.userpkg;
+
+public class PublicWithPackageVisibleConstructor {
+
+    PublicWithPackageVisibleConstructor() { }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5c98c0ed/src/test/java/org/apache/freemarker/manualtest/CustomFormatsExample.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/freemarker/manualtest/CustomFormatsExample.java 
b/src/test/java/org/apache/freemarker/manualtest/CustomFormatsExample.java
index 401ce0d..5441609 100644
--- a/src/test/java/org/apache/freemarker/manualtest/CustomFormatsExample.java
+++ b/src/test/java/org/apache/freemarker/manualtest/CustomFormatsExample.java
@@ -26,11 +26,11 @@ import java.util.Map;
 
 import org.apache.freemarker.core.AliasTemplateDateFormatFactory;
 import org.apache.freemarker.core.AliasTemplateNumberFormatFactory;
-import org.apache.freemarker.core.BaseNTemplateNumberFormatFactory;
 import org.apache.freemarker.core.Configuration;
 import org.apache.freemarker.core.TemplateDateFormatFactory;
 import org.apache.freemarker.core.TemplateException;
 import org.apache.freemarker.core.TemplateNumberFormatFactory;
+import org.apache.freemarker.core.userpkg.BaseNTemplateNumberFormatFactory;
 import org.junit.Test;
 
 @SuppressWarnings("boxing")

Reply via email to