You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by sh...@apache.org on 2016/11/21 08:07:58 UTC
svn commit: r1770621 [3/5] - in /ofbiz/trunk/specialpurpose/pricat: ./
config/ data/ entitydef/ groovyScripts/ groovyScripts/pricat/ src/
src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/
src/main/java/org/apache/ofbiz/ src/main/jav...
Added: ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/htmlreport/util/ReportEncoder.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/htmlreport/util/ReportEncoder.java?rev=1770621&view=auto
==============================================================================
--- ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/htmlreport/util/ReportEncoder.java (added)
+++ ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/htmlreport/util/ReportEncoder.java Mon Nov 21 08:07:57 2016
@@ -0,0 +1,678 @@
+/*******************************************************************************
+ * 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.ofbiz.htmlreport.util;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * The ReportEncoder class provides static methods to decode and encode data.<p>
+ *
+ * The methods in this class are substitutes for <code>java.net.URLEncoder.encode()</code> and
+ * <code>java.net.URLDecoder.decode()</code>.<p>
+ *
+ * The de- and encoding uses the same coding mechanism as JavaScript, special characters are
+ * replaced with <code>%hex</code> where hex is a two digit hex number.<p>
+ *
+ * <b>Note:</b> On the client side (browser) instead of using corresponding <code>escape</code>
+ * and <code>unescape</code> JavaScript functions, better use <code>encodeURIComponent</code> and
+ * <code>decodeURIComponent</code> functions which are work properly with unicode characters.
+ * These functions are supported in IE 5.5+ and NS 6+ only.<p>
+ *
+ */
+public final class ReportEncoder {
+
+ /** Constant for the standard <code>ISO-8859-1</code> encoding. */
+ public static final String ENCODING_ISO_8859_1 = "ISO-8859-1";
+
+ /** Constant for the standard <code>US-ASCII</code> encoding. */
+ public static final String ENCODING_US_ASCII = "US-ASCII";
+
+ /**
+ * Constant for the standard <code>UTF-8</code> encoding.<p>
+ *
+ * Default encoding for JavaScript decodeUriComponent methods is <code>UTF-8</code> by w3c standard.
+ */
+ public static final String ENCODING_UTF_8 = "UTF-8";
+
+ /** The regex pattern to match HTML entities. */
+ private static final Pattern ENTITIY_PATTERN = Pattern.compile("\\&#\\d+;");
+
+ /** The prefix for HTML entities. */
+ private static final String ENTITY_PREFIX = "&#";
+
+ /** The replacement for HTML entity prefix in parameters. */
+ private static final String ENTITY_REPLACEMENT = "$$";
+
+ /** A cache for encoding name lookup. */
+ private static Map<String, String> encodingCache = new HashMap<String, String>(16);
+
+ /** The plus entity. */
+ private static final String PLUS_ENTITY = ENTITY_PREFIX + "043;";
+
+ /**
+ * Constructor.<p>
+ */
+ private ReportEncoder() {
+ // empty
+ }
+
+ /**
+ * Adjusts the given String by making sure all characters that can be displayed
+ * in the given charset are contained as chars, whereas all other non-displayable
+ * characters are converted to HTML entities.<p>
+ *
+ * Just calls {@link #decodeHtmlEntities(String, String)} first and feeds the result
+ * to {@link #encodeHtmlEntities(String, String)}. <p>
+ *
+ * @param input the input to adjust the HTML encoding for
+ * @param encoding the charset to encode the result with\
+ *
+ * @return the input with the decoded/encoded HTML entities
+ */
+ public static String adjustHtmlEncoding(String input, String encoding) {
+
+ return encodeHtmlEntities(decodeHtmlEntities(input, encoding), encoding);
+ }
+
+ /**
+ * Changes the encoding of a byte array that represents a String.<p>
+ *
+ * @param input the byte array to convert
+ * @param oldEncoding the current encoding of the byte array
+ * @param newEncoding the new encoding of the byte array
+ *
+ * @return the byte array encoded in the new encoding
+ */
+ public static byte[] changeEncoding(byte[] input, String oldEncoding, String newEncoding) {
+
+ if ((oldEncoding == null) || (newEncoding == null)) {
+ return input;
+ }
+ if (oldEncoding.trim().equalsIgnoreCase(newEncoding.trim())) {
+ return input;
+ }
+ byte[] result = input;
+ try {
+ result = (new String(input, oldEncoding)).getBytes(newEncoding);
+ } catch (UnsupportedEncodingException e) {
+ // return value will be input value
+ }
+ return result;
+ }
+
+ /**
+ * Creates a String out of a byte array with the specified encoding, falling back
+ * to the system default in case the encoding name is not valid.<p>
+ *
+ * Use this method as a replacement for <code>new String(byte[], encoding)</code>
+ * to avoid possible encoding problems.<p>
+ *
+ * @param bytes the bytes to decode
+ * @param encoding the encoding scheme to use for decoding the bytes
+ *
+ * @return the bytes decoded to a String
+ */
+ public static String createString(byte[] bytes, String encoding) {
+
+ String enc = encoding.intern();
+ if (enc != ENCODING_UTF_8) {
+ enc = lookupEncoding(enc, null);
+ }
+ if (enc != null) {
+ try {
+ return new String(bytes, enc);
+ } catch (UnsupportedEncodingException e) {
+ // this can _never_ happen since the charset was looked up first
+ }
+ } else {
+ enc = ENCODING_UTF_8;
+ try {
+ return new String(bytes, enc);
+ } catch (UnsupportedEncodingException e) {
+ // this can also _never_ happen since the default encoding is always valid
+ }
+ }
+ // this code is unreachable in practice
+ return null;
+ }
+
+ /**
+ * Decodes a String using UTF-8 encoding, which is the standard for http data transmission
+ * with GET ant POST requests.<p>
+ *
+ * @param source the String to decode
+ *
+ * @return String the decoded source String
+ */
+ public static String decode(String source) {
+
+ return decode(source, ENCODING_UTF_8);
+ }
+
+ /**
+ * This method is a substitute for <code>URLDecoder.decode()</code>.<p>
+ *
+ * In case you don't know what encoding to use, set the value of
+ * the <code>encoding</code> parameter to <code>null</code>.
+ * This method will then default to UTF-8 encoding, which is probably the right one.<p>
+ *
+ * @param source The string to decode
+ * @param encoding The encoding to use (if null, the system default is used)
+ *
+ * @return The decoded source String
+ */
+ public static String decode(String source, String encoding) {
+
+ if (source == null) {
+ return null;
+ }
+ if (encoding != null) {
+ try {
+ return URLDecoder.decode(source, encoding);
+ } catch (java.io.UnsupportedEncodingException e) {
+ // will fallback to default
+ }
+ }
+ // fallback to default decoding
+ try {
+ return URLDecoder.decode(source, ENCODING_UTF_8);
+ } catch (java.io.UnsupportedEncodingException e) {
+ // ignore
+ }
+ return source;
+ }
+
+ /**
+ * Decodes HTML entity references like <code>&#8364;</code> that are contained in the
+ * String to a regular character, but only if that character is contained in the given
+ * encodings charset.<p>
+ *
+ * @param input the input to decode the HTML entities in
+ * @param encoding the charset to decode the input for
+ * @return the input with the decoded HTML entities
+ *
+ * @see #encodeHtmlEntities(String, String)
+ */
+ public static String decodeHtmlEntities(String input, String encoding) {
+
+ Matcher matcher = ENTITIY_PATTERN.matcher(input);
+ StringBuffer result = new StringBuffer(input.length());
+ Charset charset = Charset.forName(encoding);
+ CharsetEncoder encoder = charset.newEncoder();
+
+ while (matcher.find()) {
+ String entity = matcher.group();
+ String value = entity.substring(2, entity.length() - 1);
+ int c = Integer.valueOf(value).intValue();
+ if (c < 128) {
+ // first 128 chars are contained in almost every charset
+ entity = new String(new char[] {(char)c});
+ // this is intended as performance improvement since
+ // the canEncode() operation appears quite CPU heavy
+ } else if (encoder.canEncode((char)c)) {
+ // encoder can encode this char
+ entity = new String(new char[] {(char)c});
+ }
+ matcher.appendReplacement(result, entity);
+ }
+ matcher.appendTail(result);
+ return result.toString();
+ }
+
+ /**
+ * Decodes a string used as parameter in an uri in a way independent of other encodings/decodings applied before.<p>
+ *
+ * @param input the encoded parameter string
+ *
+ * @return the decoded parameter string
+ *
+ * @see #encodeParameter(String)
+ */
+ public static String decodeParameter(String input) {
+
+ String result = ReportStringUtil.substitute(input, ENTITY_REPLACEMENT, ENTITY_PREFIX);
+ return ReportEncoder.decodeHtmlEntities(result, ENCODING_UTF_8);
+ }
+
+ /**
+ * Encodes a String using UTF-8 encoding, which is the standard for http data transmission
+ * with GET ant POST requests.<p>
+ *
+ * @param source the String to encode
+ *
+ * @return String the encoded source String
+ */
+ public static String encode(String source) {
+
+ return encode(source, ENCODING_UTF_8);
+ }
+
+ /**
+ * This method is a substitute for <code>URLEncoder.encode()</code>.<p>
+ *
+ * In case you don't know what encoding to use, set the value of
+ * the <code>encoding</code> parameter to <code>null</code>.
+ * This method will then default to UTF-8 encoding, which is probably the right one.<p>
+ *
+ * @param source the String to encode
+ * @param encoding the encoding to use (if null, the system default is used)
+ *
+ * @return the encoded source String
+ */
+ public static String encode(String source, String encoding) {
+
+ if (source == null) {
+ return null;
+ }
+ if (encoding != null) {
+ try {
+ return URLEncoder.encode(source, encoding);
+ } catch (java.io.UnsupportedEncodingException e) {
+ // will fallback to default
+ }
+ }
+ // fallback to default encoding
+ try {
+ return URLEncoder.encode(source, ENCODING_UTF_8);
+ } catch (java.io.UnsupportedEncodingException e) {
+ // ignore
+ }
+ return source;
+ }
+
+ /**
+ * Encodes all characters that are contained in the String which can not displayed
+ * in the given encodings charset with HTML entity references
+ * like <code>&#8364;</code>.<p>
+ *
+ * This is required since a Java String is
+ * internally always stored as Unicode, meaning it can contain almost every character, but
+ * the HTML charset used might not support all such characters.<p>
+ *
+ * @param input the input to encode for HTML
+ * @param encoding the charset to encode the result with
+ *
+ * @return the input with the encoded HTML entities
+ *
+ * @see #decodeHtmlEntities(String, String)
+ */
+ public static String encodeHtmlEntities(String input, String encoding) {
+
+ StringBuffer result = new StringBuffer(input.length() * 2);
+ CharBuffer buffer = CharBuffer.wrap(input.toCharArray());
+ Charset charset = Charset.forName(encoding);
+ CharsetEncoder encoder = charset.newEncoder();
+ for (int i = 0; i < buffer.length(); i++) {
+ int c = buffer.get(i);
+ if (c < 128) {
+ // first 128 chars are contained in almost every charset
+ result.append((char)c);
+ // this is intended as performance improvement since
+ // the canEncode() operation appears quite CPU heavy
+ } else if (encoder.canEncode((char)c)) {
+ // encoder can encode this char
+ result.append((char)c);
+ } else {
+ // append HTML entity reference
+ result.append(ENTITY_PREFIX);
+ result.append(c);
+ result.append(";");
+ }
+ }
+ return result.toString();
+ }
+
+ /**
+ * Encodes all characters that are contained in the String which can not displayed
+ * in the given encodings charset with Java escaping like <code>\u20ac</code>.<p>
+ *
+ * This can be used to escape values used in Java property files.<p>
+ *
+ * @param input the input to encode for Java
+ * @param encoding the charset to encode the result with
+ *
+ * @return the input with the encoded Java entities
+ */
+ public static String encodeJavaEntities(String input, String encoding) {
+
+ StringBuffer result = new StringBuffer(input.length() * 2);
+ CharBuffer buffer = CharBuffer.wrap(input.toCharArray());
+ Charset charset = Charset.forName(encoding);
+ CharsetEncoder encoder = charset.newEncoder();
+ for (int i = 0; i < buffer.length(); i++) {
+ int c = buffer.get(i);
+ if (c < 128) {
+ // first 128 chars are contained in almost every charset
+ result.append((char)c);
+ // this is intended as performance improvement since
+ // the canEncode() operation appears quite CPU heavy
+ } else if (encoder.canEncode((char)c)) {
+ // encoder can encode this char
+ result.append((char)c);
+ } else {
+ // append Java entity reference
+ result.append("\\u");
+ String hex = Integer.toHexString(c);
+ int pad = 4 - hex.length();
+ for (int p = 0; p < pad; p++) {
+ result.append('0');
+ }
+ result.append(hex);
+ }
+ }
+ return result.toString();
+ }
+
+ /**
+ * Encodes a string used as parameter in an uri in a way independent of other encodings/decodings applied later.<p>
+ *
+ * Used to ensure that GET parameters are not wrecked by wrong or incompatible configuration settings.
+ * In order to ensure this, the String is first encoded with html entities for any character that cannot encoded
+ * in US-ASCII; additionally, the plus sign is also encoded to avoid problems with the white-space replacer.
+ * Finally, the entity prefix is replaced with characters not used as delimiters in urls.<p>
+ *
+ * @param input the parameter string
+ *
+ * @return the encoded parameter string
+ */
+ public static String encodeParameter(String input) {
+
+ String result = ReportEncoder.encodeHtmlEntities(input, ReportEncoder.ENCODING_US_ASCII);
+ result = ReportStringUtil.substitute(result, "+", PLUS_ENTITY);
+ return ReportStringUtil.substitute(result, ENTITY_PREFIX, ENTITY_REPLACEMENT);
+ }
+
+ /**
+ * Encodes a String in a way that is compatible with the JavaScript escape function.
+ *
+ * @param source The text to be encoded
+ * @param encoding the encoding type
+ *
+ * @return The JavaScript escaped string
+ */
+ public static String escape(String source, String encoding) {
+
+ // the blank is encoded into "+" not "%20" when using standard encode call
+ return ReportStringUtil.substitute(encode(source, encoding), "+", "%20");
+ }
+
+ /**
+ * Escapes special characters in a HTML-String with their number-based
+ * entity representation, for example & becomes &#38;.<p>
+ *
+ * A character <code>num</code> is replaced if<br>
+ * <code>((ch != 32) && ((ch > 122) || (ch < 48) || (ch == 60) || (ch == 62)))</code><p>
+ *
+ * @param source the String to escape
+ *
+ * @return String the escaped String
+ *
+ * @see #escapeXml(String)
+ */
+ public static String escapeHtml(String source) {
+
+ int terminatorIndex;
+ if (source == null) {
+ return null;
+ }
+ StringBuffer result = new StringBuffer(source.length() * 2);
+ for (int i = 0; i < source.length(); i++) {
+ int ch = source.charAt(i);
+ // avoid escaping already escaped characters
+ if (ch == 38) {
+ terminatorIndex = source.indexOf(";", i);
+ if (terminatorIndex > 0) {
+ if (source.substring(i + 1, terminatorIndex).matches("#[0-9]+|lt|gt|amp|quote")) {
+ result.append(source.substring(i, terminatorIndex + 1));
+ // Skip remaining chars up to (and including) ";"
+ i = terminatorIndex;
+ continue;
+ }
+ }
+ }
+ if ((ch != 32) && ((ch > 122) || (ch < 48) || (ch == 60) || (ch == 62))) {
+ result.append(ENTITY_PREFIX);
+ result.append(ch);
+ result.append(";");
+ } else {
+ result.append((char)ch);
+ }
+ }
+ return new String(result);
+ }
+
+ /**
+ * Escapes non ASCII characters in a HTML-String with their number-based
+ * entity representation, for example & becomes &#38;.<p>
+ *
+ * A character <code>num</code> is replaced if<br>
+ * <code>(ch > 255)</code><p>
+ *
+ * @param source the String to escape
+ *
+ * @return String the escaped String
+ *
+ * @see #escapeXml(String)
+ */
+ public static String escapeNonAscii(String source) {
+
+ if (source == null) {
+ return null;
+ }
+ StringBuffer result = new StringBuffer(source.length() * 2);
+ for (int i = 0; i < source.length(); i++) {
+ int ch = source.charAt(i);
+ if (ch > 255) {
+ result.append(ENTITY_PREFIX);
+ result.append(ch);
+ result.append(";");
+ } else {
+ result.append((char)ch);
+ }
+ }
+ return new String(result);
+ }
+
+ /**
+ * Encodes a String in a way that is compatible with the JavaScript escape function.
+ * Multiple blanks are encoded _multiply _with <code>%20</code>.<p>
+ *
+ * @param source The text to be encoded
+ * @param encoding the encoding type
+ *
+ * @return The JavaScript escaped string
+ */
+ public static String escapeWBlanks(String source, String encoding) {
+
+ if (ReportStringUtil.isEmpty(source)) {
+ return source;
+ }
+ StringBuffer ret = new StringBuffer(source.length() * 2);
+
+ // URLEncode the text string
+ // this produces a very similar encoding to JavaSscript encoding,
+ // except the blank which is not encoded into "%20" instead of "+"
+
+ String enc = encode(source, encoding);
+ for (int z = 0; z < enc.length(); z++) {
+ char c = enc.charAt(z);
+ if (c == '+') {
+ ret.append("%20");
+ } else {
+ ret.append(c);
+ }
+ }
+ return ret.toString();
+ }
+
+ /**
+ * Escapes a String so it may be printed as text content or attribute
+ * value in a HTML page or an XML file.<p>
+ *
+ * This method replaces the following characters in a String:
+ * <ul>
+ * <li><b><</b> with &lt;
+ * <li><b>></b> with &gt;
+ * <li><b>&</b> with &amp;
+ * <li><b>"</b> with &quot;
+ * </ul><p>
+ *
+ * @param source the string to escape
+ *
+ * @return the escaped string
+ *
+ * @see #escapeHtml(String)
+ */
+ public static String escapeXml(String source) {
+
+ return escapeXml(source, false);
+ }
+
+ /**
+ * Escapes a String so it may be printed as text content or attribute
+ * value in a HTML page or an XML file.<p>
+ *
+ * This method replaces the following characters in a String:
+ * <ul>
+ * <li><b><</b> with &lt;
+ * <li><b>></b> with &gt;
+ * <li><b>&</b> with &amp;
+ * <li><b>"</b> with &quot;
+ * </ul><p>
+ *
+ * @param source the string to escape
+ * @param doubleEscape if <code>false</code>, all entities that already are escaped are left untouched
+ *
+ * @return the escaped string
+ *
+ * @see #escapeHtml(String)
+ */
+ public static String escapeXml(String source, boolean doubleEscape) {
+
+ if (source == null) {
+ return null;
+ }
+ StringBuffer result = new StringBuffer(source.length() * 2);
+
+ for (int i = 0; i < source.length(); ++i) {
+ char ch = source.charAt(i);
+ switch (ch) {
+ case '<':
+ result.append("<");
+ break;
+ case '>':
+ result.append(">");
+ break;
+ case '&':
+ // don't escape already escaped international and special characters
+ if (!doubleEscape) {
+ int terminatorIndex = source.indexOf(";", i);
+ if (terminatorIndex > 0) {
+ if (source.substring(i + 1, terminatorIndex).matches("#[0-9]+")) {
+ result.append(ch);
+ break;
+ }
+ }
+ }
+ // note that to other "break" in the above "if" block
+ result.append("&");
+ break;
+ case '"':
+ result.append(""");
+ break;
+ default:
+ result.append(ch);
+ }
+ }
+ return new String(result);
+ }
+
+ /**
+ * Checks if a given encoding name is actually supported, and if so
+ * resolves it to it's canonical name, if not it returns the given fallback
+ * value.<p>
+ *
+ * Charsets have a set of aliases. For example, valid aliases for "UTF-8"
+ * are "UTF8", "utf-8" or "utf8". This method resolves any given valid charset name
+ * to it's "canonical" form, so that simple String comparison can be used
+ * when checking charset names internally later.<p>
+ *
+ * Please see <a href="http://www.iana.org/assignments/character-sets">http://www.iana.org/assignments/character-sets</a>
+ * for a list of valid charset alias names.<p>
+ *
+ * @param encoding the encoding to check and resolve
+ * @param fallback the fallback encoding scheme
+ *
+ * @return the resolved encoding name, or the fallback value
+ */
+ public static String lookupEncoding(String encoding, String fallback) {
+
+ String result = (String) encodingCache.get(encoding);
+ if (result != null) {
+ return result;
+ }
+
+ try {
+ result = Charset.forName(encoding).name();
+ encodingCache.put(encoding, result);
+ return result;
+ } catch (Throwable t) {
+ // we will use the default value as fallback
+ }
+
+ return fallback;
+ }
+
+ /**
+ * Decodes a String in a way that is compatible with the JavaScript
+ * unescape function.<p>
+ *
+ * @param source The String to be decoded
+ * @param encoding the encoding type
+ *
+ * @return The JavaScript unescaped String
+ */
+ public static String unescape(String source, String encoding) {
+
+ if (source == null) {
+ return null;
+ }
+ int len = source.length();
+ // to use standard decoder we need to replace '+' with "%20" (space)
+ StringBuffer preparedSource = new StringBuffer(len);
+ for (int i = 0; i < len; i++) {
+ char c = source.charAt(i);
+ if (c == '+') {
+ preparedSource.append("%20");
+ } else {
+ preparedSource.append(c);
+ }
+ }
+ return decode(preparedSource.toString(), encoding);
+ }
+}
\ No newline at end of file
Added: ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/htmlreport/util/ReportStringUtil.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/htmlreport/util/ReportStringUtil.java?rev=1770621&view=auto
==============================================================================
--- ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/htmlreport/util/ReportStringUtil.java (added)
+++ ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/htmlreport/util/ReportStringUtil.java Mon Nov 21 08:07:57 2016
@@ -0,0 +1,570 @@
+/*******************************************************************************
+ * 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.ofbiz.htmlreport.util;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * Provides String utility functions.<p>
+ *
+ */
+public final class ReportStringUtil {
+
+ /** Constant for <code>"false"</code>. */
+ public static final String FALSE = Boolean.toString(false);
+
+ /** a convenient shorthand to the line separator constant. */
+ public static final String LINE_SEPARATOR = System.getProperty("line.separator");
+
+ /** Contains all chars that end a sentence in the {@link #trimToSize(String, int, int, String)} method. */
+ public static final char[] SENTENCE_ENDING_CHARS = {'.', '!', '?'};
+
+ /** a convenient shorthand for tabulations. */
+ public static final String TABULATOR = " ";
+
+ /** Constant for <code>"true"</code>. */
+ public static final String TRUE = Boolean.toString(true);
+
+ /** Day constant. */
+ private static final long DAYS = 1000 * 60 * 60 * 24;
+
+ /** Hour constant. */
+ private static final long HOURS = 1000 * 60 * 60;
+
+ /** Minute constant. */
+ private static final long MINUTES = 1000 * 60;
+
+ /** Second constant. */
+ private static final long SECONDS = 1000;
+
+ /**
+ * Default constructor (empty), private because this class has only
+ * static methods.<p>
+ */
+ private ReportStringUtil() {
+ // empty
+ }
+
+ /**
+ * Changes the filename suffix.
+ *
+ * @param filename the filename to be changed
+ * @param suffix the new suffix of the file
+ *
+ * @return the filename with the replaced suffix
+ */
+ public static String changeFileNameSuffixTo(String filename, String suffix) {
+
+ int dotPos = filename.lastIndexOf('.');
+ if (dotPos != -1) {
+ return filename.substring(0, dotPos + 1) + suffix;
+ } else {
+ // the string has no suffix
+ return filename;
+ }
+ }
+
+ /**
+ * Returns a string representation for the given collection using the given separator.<p>
+ *
+ * @param collection the collection to print
+ * @param separator the item separator
+ *
+ * @return the string representation for the given collection
+ */
+ public static String collectionAsString(Collection<String> collection, String separator) {
+
+ StringBuffer string = new StringBuffer(128);
+ Iterator<String> it = collection.iterator();
+ while (it.hasNext()) {
+ string.append(it.next());
+ if (it.hasNext()) {
+ string.append(separator);
+ }
+ }
+ return string.toString();
+ }
+
+ /**
+ * Replaces occurrences of special control characters in the given input with
+ * a HTML representation.<p>
+ *
+ * This method currently replaces line breaks to <code><br/></code> and special HTML chars
+ * like <code>< > & "</code> with their HTML entity representation.<p>
+ *
+ * @param source the String to escape
+ *
+ * @return the escaped String
+ */
+ public static String escapeHtml(String source) {
+
+ if (source == null) {
+ return null;
+ }
+ source = ReportEncoder.escapeXml(source);
+ source = substitute(source, "\r", "");
+ source = substitute(source, "\n", "<br/>\n");
+ return source;
+ }
+
+ /**
+ * Escapes a String so it may be used in JavaScript String definitions.<p>
+ *
+ * This method replaces line breaks, quotation marks and \ characters.<p>
+ *
+ * @param source the String to escape
+ *
+ * @return the escaped String
+ */
+ public static String escapeJavaScript(String source) {
+
+ source = substitute(source, "\\", "\\\\");
+ source = substitute(source, "\"", "\\\"");
+ source = substitute(source, "\'", "\\\'");
+ source = substitute(source, "\r\n", "\\n");
+ source = substitute(source, "\n", "\\n");
+ return source;
+ }
+
+ /**
+ * Escapes a String so it may be used as a Perl5 regular expression.<p>
+ *
+ * This method replaces the following characters in a String:<br>
+ * <code>{}[]()\$^.*+/</code><p>
+ *
+ * @param source the string to escape
+ *
+ * @return the escaped string
+ */
+ public static String escapePattern(String source) {
+
+ if (source == null) {
+ return null;
+ }
+ StringBuffer result = new StringBuffer(source.length() * 2);
+ for (int i = 0; i < source.length(); ++i) {
+ char ch = source.charAt(i);
+ switch (ch) {
+ case '\\':
+ result.append("\\\\");
+ break;
+ case '/':
+ result.append("\\/");
+ break;
+ case '$':
+ result.append("\\$");
+ break;
+ case '^':
+ result.append("\\^");
+ break;
+ case '.':
+ result.append("\\.");
+ break;
+ case '*':
+ result.append("\\*");
+ break;
+ case '+':
+ result.append("\\+");
+ break;
+ case '|':
+ result.append("\\|");
+ break;
+ case '?':
+ result.append("\\?");
+ break;
+ case '{':
+ result.append("\\{");
+ break;
+ case '}':
+ result.append("\\}");
+ break;
+ case '[':
+ result.append("\\[");
+ break;
+ case ']':
+ result.append("\\]");
+ break;
+ case '(':
+ result.append("\\(");
+ break;
+ case ')':
+ result.append("\\)");
+ break;
+ default:
+ result.append(ch);
+ }
+ }
+ return new String(result);
+ }
+
+ /**
+ * Formats a runtime in the format hh:mm:ss, to be used e.g. in reports.<p>
+ *
+ * If the runtime is greater then 24 hours, the format dd:hh:mm:ss is used.<p>
+ *
+ * @param runtime the time to format
+ *
+ * @return the formatted runtime
+ */
+ public static String formatRuntime(long runtime) {
+
+ long seconds = (runtime / SECONDS) % 60;
+ long minutes = (runtime / MINUTES) % 60;
+ long hours = (runtime / HOURS) % 24;
+ long days = runtime / DAYS;
+ StringBuffer strBuf = new StringBuffer();
+
+ if (days > 0) {
+ if (days < 10) {
+ strBuf.append('0');
+ }
+ strBuf.append(days);
+ strBuf.append(':');
+ }
+
+ if (hours < 10) {
+ strBuf.append('0');
+ }
+ strBuf.append(hours);
+ strBuf.append(':');
+
+ if (minutes < 10) {
+ strBuf.append('0');
+ }
+ strBuf.append(minutes);
+ strBuf.append(':');
+
+ if (seconds < 10) {
+ strBuf.append('0');
+ }
+ strBuf.append(seconds);
+
+ return strBuf.toString();
+ }
+
+ /**
+ * Returns <code>true</code> if the provided String is either <code>null</code>
+ * or the empty String <code>""</code>.<p>
+ *
+ * @param value the value to check
+ *
+ * @return true, if the provided value is null or the empty String, false otherwise
+ */
+ public static boolean isEmpty(String value) {
+
+ return (value == null) || (value.length() == 0);
+ }
+
+ /**
+ * Returns <code>true</code> if the provided String is either <code>null</code>
+ * or contains only white spaces.<p>
+ *
+ * @param value the value to check
+ *
+ * @return true, if the provided value is null or contains only white spaces, false otherwise
+ */
+ public static boolean isEmptyOrWhitespaceOnly(String value) {
+
+ return isEmpty(value) || (value.trim().length() == 0);
+ }
+
+ /**
+ * Returns <code>true</code> if the provided Objects are either both <code>null</code>
+ * or equal according to {@link Object#equals(Object)}.<p>
+ *
+ * @param value1 the first object to compare
+ * @param value2 the second object to compare
+ *
+ * @return <code>true</code> if the provided Objects are either both <code>null</code>
+ * or equal according to {@link Object#equals(Object)}
+ */
+ public static boolean isEqual(Object value1, Object value2) {
+
+ if (value1 == null) {
+ return (value2 == null);
+ }
+ return value1.equals(value2);
+ }
+
+ /**
+ * Returns <code>true</code> if the provided String is neither <code>null</code>
+ * nor the empty String <code>""</code>.<p>
+ *
+ * @param value the value to check
+ *
+ * @return true, if the provided value is not null and not the empty String, false otherwise
+ */
+ public static boolean isNotEmpty(String value) {
+
+ return (value != null) && (value.length() != 0);
+ }
+
+ /**
+ * Returns <code>true</code> if the provided String is neither <code>null</code>
+ * nor contains only white spaces.<p>
+ *
+ * @param value the value to check
+ *
+ * @return <code>true</code>, if the provided value is <code>null</code>
+ * or contains only white spaces, <code>false</code> otherwise
+ */
+ public static boolean isNotEmptyOrWhitespaceOnly(String value) {
+
+ return (value != null) && (value.trim().length() > 0);
+ }
+
+ /**
+ * Returns the last index of any of the given chars in the given source.<p>
+ *
+ * If no char is found, -1 is returned.<p>
+ *
+ * @param source the source to check
+ * @param chars the chars to find
+ *
+ * @return the last index of any of the given chars in the given source, or -1
+ */
+ public static int lastIndexOf(String source, char[] chars) {
+
+ // now try to find an "sentence ending" char in the text in the "findPointArea"
+ int result = -1;
+ for (int i = 0; i < chars.length; i++) {
+ int pos = source.lastIndexOf(chars[i]);
+ if (pos > result) {
+ // found new last char
+ result = pos;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Returns the last index a whitespace char the given source.<p>
+ *
+ * If no whitespace char is found, -1 is returned.<p>
+ *
+ * @param source the source to check
+ *
+ * @return the last index a whitespace char the given source, or -1
+ */
+ public static int lastWhitespaceIn(String source) {
+
+ if (isEmpty(source)) {
+ return -1;
+ }
+ int pos = -1;
+ for (int i = source.length() - 1; i >= 0; i--) {
+ if (Character.isWhitespace(source.charAt(i))) {
+ pos = i;
+ break;
+ }
+ }
+ return pos;
+ }
+
+ /**
+ * Substitutes <code>searchString</code> in the given source String with <code>replaceString</code>.<p>
+ *
+ * This is a high-performance implementation which should be used as a replacement for
+ * <code>{@link String#replaceAll(java.lang.String, java.lang.String)}</code> in case no
+ * regular expression evaluation is required.<p>
+ *
+ * @param source the content which is scanned
+ * @param searchString the String which is searched in content
+ * @param replaceString the String which replaces <code>searchString</code>
+ *
+ * @return the substituted String
+ */
+ public static String substitute(String source, String searchString, String replaceString) {
+
+ if (source == null) {
+ return null;
+ }
+
+ if (isEmpty(searchString)) {
+ return source;
+ }
+
+ if (replaceString == null) {
+ replaceString = "";
+ }
+ int len = source.length();
+ int sl = searchString.length();
+ int rl = replaceString.length();
+ int length;
+ if (sl == rl) {
+ length = len;
+ } else {
+ int c = 0;
+ int s = 0;
+ int e;
+ while ((e = source.indexOf(searchString, s)) != -1) {
+ c++;
+ s = e + sl;
+ }
+ if (c == 0) {
+ return source;
+ }
+ length = len - (c * (sl - rl));
+ }
+
+ int s = 0;
+ int e = source.indexOf(searchString, s);
+ if (e == -1) {
+ return source;
+ }
+ StringBuffer sb = new StringBuffer(length);
+ while (e != -1) {
+ sb.append(source.substring(s, e));
+ sb.append(replaceString);
+ s = e + sl;
+ e = source.indexOf(searchString, s);
+ }
+ e = len;
+ sb.append(source.substring(s, e));
+ return sb.toString();
+ }
+
+ /**
+ * Returns the java String literal for the given String. <p>
+ *
+ * This is the form of the String that had to be written into source code
+ * using the unicode escape sequence for special characters. <p>
+ *
+ * Example: "�" would be transformed to "\\u00C4".<p>
+ *
+ * @param s a string that may contain non-ascii characters
+ *
+ * @return the java unicode escaped string Literal of the given input string
+ */
+ public static String toUnicodeLiteral(String s) {
+
+ StringBuffer result = new StringBuffer();
+ char[] carr = s.toCharArray();
+
+ String unicode;
+ for (int i = 0; i < carr.length; i++) {
+ result.append("\\u");
+ // append leading zeros
+ unicode = Integer.toHexString(carr[i]).toUpperCase();
+ for (int j = 4 - unicode.length(); j > 0; j--) {
+ result.append("0");
+ }
+ result.append(unicode);
+ }
+ return result.toString();
+ }
+
+ /**
+ * Returns a substring of the source, which is at most length characters long.<p>
+ *
+ * This is the same as calling {@link #trimToSize(String, int, String)} with the
+ * parameters <code>(source, length, " ...")</code>.<p>
+ *
+ * @param source the string to trim
+ * @param length the maximum length of the string to be returned
+ *
+ * @return a substring of the source, which is at most length characters long
+ */
+ public static String trimToSize(String source, int length) {
+
+ return trimToSize(source, length, length, " ...");
+ }
+
+ /**
+ * Returns a substring of the source, which is at most length characters long.<p>
+ *
+ * If a char is cut, the given <code>suffix</code> is appended to the result.<p>
+ *
+ * This is almost the same as calling {@link #trimToSize(String, int, int, String)} with the
+ * parameters <code>(source, length, length*, suffix)</code>. If <code>length</code>
+ * if larger then 100, then <code>length* = length / 2</code>,
+ * otherwise <code>length* = length</code>.<p>
+ *
+ * @param source the string to trim
+ * @param length the maximum length of the string to be returned
+ * @param suffix the suffix to append in case the String was trimmed
+ *
+ * @return a substring of the source, which is at most length characters long
+ */
+ public static String trimToSize(String source, int length, String suffix) {
+
+ int area = (length > 100) ? length / 2 : length;
+ return trimToSize(source, length, area, suffix);
+ }
+
+ /**
+ * Returns a substring of the source, which is at most length characters long, cut
+ * in the last <code>area</code> chars in the source at a sentence ending char or whitespace.<p>
+ *
+ * If a char is cut, the given <code>suffix</code> is appended to the result.<p>
+ *
+ * @param source the string to trim
+ * @param length the maximum length of the string to be returned
+ * @param area the area at the end of the string in which to find a sentence ender or whitespace
+ * @param suffix the suffix to append in case the String was trimmed
+ *
+ * @return a substring of the source, which is at most length characters long
+ */
+ public static String trimToSize(String source, int length, int area, String suffix) {
+
+ if ((source == null) || (source.length() <= length)) {
+ // no operation is required
+ return source;
+ }
+ if (isEmpty(suffix)) {
+ // we need an empty suffix
+ suffix = "";
+ }
+ // must remove the length from the after sequence chars since these are always added in the end
+ int modLength = length - suffix.length();
+ if (modLength <= 0) {
+ // we are to short, return beginning of the suffix
+ return suffix.substring(0, length);
+ }
+ int modArea = area + suffix.length();
+ if ((modArea > modLength) || (modArea < 0)) {
+ // area must not be longer then max length
+ modArea = modLength;
+ }
+
+ // first reduce the String to the maximum allowed length
+ String findPointSource = source.substring(modLength - modArea, modLength);
+
+ String result;
+ // try to find an "sentence ending" char in the text
+ int pos = lastIndexOf(findPointSource, SENTENCE_ENDING_CHARS);
+ if (pos >= 0) {
+ // found a sentence ender in the lookup area, keep the sentence ender
+ result = source.substring(0, modLength - modArea + pos + 1) + suffix;
+ } else {
+ // no sentence ender was found, try to find a whitespace
+ pos = lastWhitespaceIn(findPointSource);
+ if (pos >= 0) {
+ // found a whitespace, don't keep the whitespace
+ result = source.substring(0, modLength - modArea + pos) + suffix;
+ } else {
+ // not even a whitespace was found, just cut away what's to long
+ result = source.substring(0, modLength) + suffix;
+ }
+ }
+
+ return result;
+ }
+}
\ No newline at end of file
Added: ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/pricat/AbstractPricatParser.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/pricat/AbstractPricatParser.java?rev=1770621&view=auto
==============================================================================
--- ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/pricat/AbstractPricatParser.java (added)
+++ ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/pricat/AbstractPricatParser.java Mon Nov 21 08:07:57 2016
@@ -0,0 +1,663 @@
+/*******************************************************************************
+ * 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.ofbiz.pricat;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.apache.poi.hssf.usermodel.HSSFDataFormatter;
+import org.apache.poi.ss.usermodel.ClientAnchor.AnchorType;
+import org.apache.poi.ss.util.CellAddress;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.ss.util.CellReference;
+import org.apache.poi.ss.util.WorkbookUtil;
+import org.apache.poi.xssf.usermodel.OFBizPricatUtil;
+import org.apache.poi.xssf.usermodel.XSSFAnchor;
+import org.apache.poi.xssf.usermodel.XSSFCell;
+import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
+import org.apache.poi.xssf.usermodel.XSSFComment;
+import org.apache.poi.xssf.usermodel.XSSFCreationHelper;
+import org.apache.poi.xssf.usermodel.XSSFDrawing;
+import org.apache.poi.xssf.usermodel.XSSFFont;
+import org.apache.poi.xssf.usermodel.XSSFPicture;
+import org.apache.poi.xssf.usermodel.XSSFPictureData;
+import org.apache.poi.xssf.usermodel.XSSFRichTextString;
+import org.apache.poi.xssf.usermodel.XSSFRow;
+import org.apache.poi.xssf.usermodel.XSSFShape;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.apache.commons.fileupload.FileItem;
+
+import org.apache.ofbiz.htmlreport.InterfaceReport;
+import org.apache.ofbiz.order.finaccount.FinAccountHelper;
+import org.apache.ofbiz.base.util.Debug;
+import org.apache.ofbiz.base.util.FileUtil;
+import org.apache.ofbiz.base.util.UtilDateTime;
+import org.apache.ofbiz.base.util.UtilMisc;
+import org.apache.ofbiz.base.util.UtilProperties;
+import org.apache.ofbiz.base.util.UtilValidate;
+import org.apache.ofbiz.entity.Delegator;
+import org.apache.ofbiz.entity.GenericEntityException;
+import org.apache.ofbiz.entity.GenericValue;
+import org.apache.ofbiz.entity.condition.EntityCondition;
+import org.apache.ofbiz.entity.condition.EntityOperator;
+import org.apache.ofbiz.entity.util.EntityUtil;
+import org.apache.ofbiz.service.LocalDispatcher;
+import org.apache.ofbiz.service.ServiceUtil;
+
+/**
+ * Abstract class of pricat parser.
+ *
+ */
+public abstract class AbstractPricatParser implements InterfacePricatParser {
+
+ public static final String module = AbstractPricatParser.class.getName();
+
+ protected LocalDispatcher dispatcher;
+
+ protected Delegator delegator;
+
+ protected List<FileItem> fileItems;
+
+ protected File pricatFile;
+
+ protected String userLoginId;
+
+ protected GenericValue userLogin;
+
+ protected String pricatFileVersion;
+
+ protected String currencyId;
+
+ protected Map<CellReference, String> errorMessages = new HashMap<CellReference, String>();
+
+ protected HSSFDataFormatter formatter = new HSSFDataFormatter();
+
+ protected Map<String, String[]> facilities = new HashMap<String, String[]>();
+
+ protected HttpSession session;
+
+ protected List<EntityCondition> basicCategoryConds;
+
+ protected List<EntityCondition> basicBrandConds;
+
+ protected String selectedPricatType = DEFAULT_PRICAT_TYPE;
+
+ protected String selectedFacilityId;
+
+ protected InterfaceReport report;
+
+ protected Locale locale;
+
+ protected long sequenceNum = -1L;
+
+ public AbstractPricatParser(LocalDispatcher dispatcher, Delegator delegator, Locale locale, InterfaceReport report, Map<String, String[]> facilities, File pricatFile, GenericValue userLogin) {
+ this.dispatcher = dispatcher;
+ this.delegator = delegator;
+ this.locale = locale;
+ this.report = report;
+ this.userLogin = userLogin;
+ if (UtilValidate.isNotEmpty(userLogin)) {
+ this.userLoginId = userLogin.getString("userLoginId");
+ }
+ this.facilities = facilities;
+ this.pricatFile = pricatFile;
+ initBasicConds(UtilMisc.toList(userLogin.getString("partyId")));
+ }
+
+ public void writeCommentsToFile(XSSFWorkbook workbook, XSSFSheet sheet) {
+ report.println();
+ report.print(UtilProperties.getMessage(resource, "WriteCommentsBackToExcel", locale), InterfaceReport.FORMAT_NOTE);
+ FileOutputStream fos = null;
+ XSSFCreationHelper factory = workbook.getCreationHelper();
+ XSSFFont boldFont = workbook.createFont();
+ boldFont.setFontName("Arial");
+ boldFont.setBold(true);
+ boldFont.setCharSet(134);
+ boldFont.setFontHeightInPoints((short) 9);
+ XSSFFont plainFont = workbook.createFont();
+ plainFont.setFontName("Arial");
+ plainFont.setCharSet(134);
+ plainFont.setFontHeightInPoints((short) 9);
+
+ XSSFSheet errorSheet = null;
+ if (errorMessages.keySet().size() > 0) {
+ String errorSheetName = UtilDateTime.nowDateString("yyyy-MM-dd HHmm") + " Errors";
+ errorSheetName = WorkbookUtil.createSafeSheetName(errorSheetName);
+ errorSheet = workbook.createSheet(errorSheetName);
+ workbook.setSheetOrder(errorSheetName, 0);
+ workbook.setActiveSheet(workbook.getSheetIndex(errorSheetName));
+ XSSFDrawing drawingPatriarch = errorSheet.getDrawingPatriarch();
+ if (drawingPatriarch == null) {
+ drawingPatriarch = errorSheet.createDrawingPatriarch();
+ }
+ for (int i = 0; i <= getHeaderRowNo(); i++) {
+ XSSFRow newRow = errorSheet.createRow(i);
+ XSSFRow row = sheet.getRow(i);
+ newRow.setHeight(row.getHeight());
+ copyRow(row, newRow, factory, drawingPatriarch);
+ }
+
+ // copy merged regions
+ for (int i = 0; i < sheet.getNumMergedRegions(); i++) {
+ CellRangeAddress mergedRegion = sheet.getMergedRegion(i);
+ if (mergedRegion.getFirstRow() < getHeaderRowNo()) {
+ errorSheet.addMergedRegion(mergedRegion);
+ }
+ }
+
+ // copy images
+ List<XSSFPictureData> pics = workbook.getAllPictures();
+ List<XSSFShape> shapes = sheet.getDrawingPatriarch().getShapes();
+ for (int i = 0; i < shapes.size(); i++) {
+ XSSFShape shape = shapes.get(i);
+ XSSFAnchor anchor = shape.getAnchor();
+ if (shape instanceof XSSFPicture && anchor instanceof XSSFClientAnchor) {
+ XSSFPicture pic = (XSSFPicture) shape;
+ XSSFClientAnchor clientAnchor = (XSSFClientAnchor) anchor;
+ if (clientAnchor.getRow1() < getHeaderRowNo()) {
+ for (int j = 0; j < pics.size(); j++) {
+ XSSFPictureData picture = pics.get(j);
+ if (picture.getPackagePart().getPartName().equals(pic.getPictureData().getPackagePart().getPartName())) {
+ drawingPatriarch.createPicture(clientAnchor, j);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ try {
+ // set comments in the original sheet
+ XSSFDrawing patriarch = sheet.getDrawingPatriarch();
+ for (CellReference cell : errorMessages.keySet()) {
+ if (cell != null && errorMessages.get(cell) != null) {
+ XSSFComment comment = sheet.getCellComment(new CellAddress(cell.getRow(), cell.getCol()));
+ boolean isNewComment = false;
+ if (comment == null) {
+ XSSFClientAnchor anchor = factory.createClientAnchor();
+ anchor.setDx1(100);
+ anchor.setDx2(100);
+ anchor.setDy1(100);
+ anchor.setDy2(100);
+ anchor.setCol1(cell.getCol());
+ anchor.setCol2(cell.getCol() + 4);
+ anchor.setRow1(cell.getRow());
+ anchor.setRow2(cell.getRow() + 4);
+ anchor.setAnchorType(AnchorType.DONT_MOVE_AND_RESIZE);
+
+ comment = patriarch.createCellComment(anchor);
+ isNewComment = true;
+ }
+ XSSFRichTextString rts = factory.createRichTextString("OFBiz PriCat:\n");
+ rts.applyFont(boldFont);
+ rts.append(errorMessages.get(cell), plainFont);
+ comment.setString(rts);
+ comment.setAuthor("Apache OFBiz PriCat");
+ if (isNewComment) {
+ sheet.getRow(cell.getRow()).getCell(cell.getCol()).setCellComment(comment);
+ OFBizPricatUtil.formatCommentShape(sheet, cell);
+ }
+ }
+ }
+
+ // set comments in the new error sheet
+ XSSFDrawing errorPatriarch = errorSheet.getDrawingPatriarch();
+ int newRowNum = getHeaderRowNo() + 1;
+ Map<Integer, Integer> rowMapping = new HashMap<Integer, Integer>();
+ for (CellReference cell : errorMessages.keySet()) {
+ if (cell != null && errorMessages.get(cell) != null) {
+ XSSFRow row = sheet.getRow(cell.getRow());
+ Integer rowNum = Integer.valueOf(row.getRowNum());
+ int errorRow = newRowNum;
+ if (rowMapping.containsKey(rowNum)) {
+ errorRow = rowMapping.get(rowNum).intValue();
+ } else {
+ XSSFRow newRow = errorSheet.getRow(errorRow);
+ if (newRow == null) {
+ newRow = errorSheet.createRow(errorRow);
+ }
+ rowMapping.put(rowNum, Integer.valueOf(errorRow));
+ newRow.setHeight(row.getHeight());
+ copyRow(row, newRow, factory, errorPatriarch);
+ newRowNum ++;
+ }
+ }
+ }
+
+ // write to file
+ if (sequenceNum > 0L) {
+ File commentedExcel = FileUtil.getFile(tempFilesFolder + userLoginId + "/" + sequenceNum + ".xlsx");
+ fos = new FileOutputStream(commentedExcel);
+ workbook.write(fos);
+ } else {
+ fos = new FileOutputStream(pricatFile);
+ workbook.write(fos);
+ }
+ fos.flush();
+ fos.close();
+ workbook.close();
+ } catch (FileNotFoundException e) {
+ report.println(e);
+ Debug.logError(e, module);
+ } catch (IOException e) {
+ report.println(e);
+ Debug.logError(e, module);
+ } finally {
+ if (fos != null) {
+ try {
+ fos.close();
+ } catch (IOException e) {
+ Debug.logError(e, module);
+ }
+ }
+ if (workbook != null) {
+ try {
+ workbook.close();
+ } catch (IOException e) {
+ Debug.logError(e, module);
+ }
+ }
+ }
+ report.println(UtilProperties.getMessage(resource, "ok", locale), InterfaceReport.FORMAT_OK);
+ report.println();
+ }
+
+ private void copyRow(XSSFRow sourceRow, XSSFRow targetRow, XSSFCreationHelper factory, XSSFDrawing patriarch) {
+ for (int j = 0; j < sourceRow.getPhysicalNumberOfCells(); j++) {
+ XSSFCell cell = sourceRow.getCell(j);
+ if (cell != null) {
+ XSSFCell newCell = targetRow.createCell(j);
+ int cellType = cell.getCellType();
+ newCell.setCellType(cellType);
+ switch (cellType) {
+ case XSSFCell.CELL_TYPE_BOOLEAN:
+ newCell.setCellValue(cell.getBooleanCellValue());
+ break;
+ case XSSFCell.CELL_TYPE_ERROR:
+ newCell.setCellErrorValue(cell.getErrorCellValue());
+ break;
+ case XSSFCell.CELL_TYPE_FORMULA:
+ newCell.setCellFormula(cell.getCellFormula());
+ break;
+ case XSSFCell.CELL_TYPE_NUMERIC:
+ newCell.setCellValue(cell.getNumericCellValue());
+ break;
+ case XSSFCell.CELL_TYPE_STRING:
+ newCell.setCellValue(cell.getRichStringCellValue());
+ break;
+ default:
+ newCell.setCellValue(formatter.formatCellValue(cell));
+ }
+ if (cell.getCellComment() != null) {
+ XSSFClientAnchor anchor = factory.createClientAnchor();
+ anchor.setDx1(100);
+ anchor.setDx2(100);
+ anchor.setDy1(100);
+ anchor.setDy2(100);
+ anchor.setCol1(newCell.getColumnIndex());
+ anchor.setCol2(newCell.getColumnIndex() + 4);
+ anchor.setRow1(newCell.getRowIndex());
+ anchor.setRow2(newCell.getRowIndex() + 4);
+ anchor.setAnchorType(AnchorType.DONT_MOVE_AND_RESIZE);
+
+ XSSFComment comment = patriarch.createCellComment(anchor);
+ comment.setString(cell.getCellComment().getString());
+ newCell.setCellComment(comment);
+ }
+ newCell.setCellStyle(cell.getCellStyle());
+ newCell.getSheet().setColumnWidth(newCell.getColumnIndex(), cell.getSheet().getColumnWidth(cell.getColumnIndex()));
+ }
+ }
+ }
+
+ public void initBasicConds(List<String> orgPartyIds) {
+ basicCategoryConds = new ArrayList<EntityCondition>();
+ basicCategoryConds.add(EntityCondition.makeCondition("isPublic", "N"));
+ //basicCategoryConds.add(EntityCondition.makeCondition("isDefault", "Y"));
+
+ basicBrandConds = new ArrayList<EntityCondition>();
+ basicBrandConds.add(EntityCondition.makeCondition("isPublic", "N"));
+ basicBrandConds.add(EntityCondition.makeCondition("productFeatureTypeId", "BRAND"));
+
+ List<EntityCondition> partyIdConds = new ArrayList<EntityCondition>();
+ for (String orgPartyId : orgPartyIds) {
+ partyIdConds.add(EntityCondition.makeCondition("ownerPartyId", orgPartyId));
+ }
+ if (UtilValidate.isNotEmpty(partyIdConds)) {
+ basicCategoryConds.add(EntityCondition.makeCondition(partyIdConds, EntityOperator.OR));
+ basicBrandConds.add(EntityCondition.makeCondition(partyIdConds, EntityOperator.OR));
+ }
+ }
+
+ public Map<String, Object> updateSkuPrice(String skuId, String ownerPartyId, BigDecimal memberPrice) {
+ return ServiceUtil.returnSuccess();
+ }
+
+ public Map<String, Object> updateColorAndDimension(String productId, String ownerPartyId, String color, String dimension) {
+ Map<String, Object> results = ServiceUtil.returnSuccess();
+ results.put("colorId", "sampleColorId");
+ results.put("dimensionId", "sampleDimensionId");
+ return results;
+ }
+
+ public Map<String, Object> getDimensionIds(String productId, String ownerPartyId, String dimension) {
+ Map<String, Object> results = ServiceUtil.returnSuccess();
+ results.put("dimensionId", "sampleDimensionId");
+ return results;
+ }
+
+ public Map<String, Object> getColorIds(String productId, String ownerPartyId, String color) {
+ Map<String, Object> results = ServiceUtil.returnSuccess();
+ results.put("foundColor", Boolean.TRUE);
+ results.put("colorId", "sampleColorId");
+ return results;
+ }
+
+ public String getBrandId(String brandName, String ownerPartyId) {
+ return "sampleBrandId";
+ }
+
+ public boolean isNumOfSheetsOK(XSSFWorkbook workbook) {
+ report.print(UtilProperties.getMessage(resource, "CheckPricatHasSheet", locale), InterfaceReport.FORMAT_NOTE);
+ int sheets = workbook.getNumberOfSheets();
+ if (sheets < 1) {
+ report.println(UtilProperties.getMessage(resource, "PricatTableNoSheet", locale), InterfaceReport.FORMAT_ERROR);
+ return false;
+ } else if (sheets >= 1) {
+ report.println(UtilProperties.getMessage(resource, "ok", locale), InterfaceReport.FORMAT_OK);
+ report.println(UtilProperties.getMessage(resource, "PricatTableOnlyParse1stSheet", locale), InterfaceReport.FORMAT_WARNING);
+ }
+ return true;
+ }
+
+ /**
+ * Get data by version definition.
+ *
+ * @param row
+ * @param colNames
+ * @param size
+ * @return
+ */
+ public List<Object> getCellContents(XSSFRow row, List<Object[]> colNames, int size) {
+ List<Object> results = new ArrayList<Object>();
+ boolean foundError = false;
+ if (isEmptyRow(row, size, true)) {
+ return null;
+ }
+ for (int i = 0; i < size; i++) {
+ XSSFCell cell = null;
+ if (row.getPhysicalNumberOfCells() > i) {
+ cell = row.getCell(i);
+ }
+ if (cell == null) {
+ if (((Boolean) colNames.get(i)[2]).booleanValue()) {
+ report.print(UtilProperties.getMessage(resource, "ErrorColCannotEmpty", new Object[] {colNames.get(i)[0]}, locale), InterfaceReport.FORMAT_WARNING);
+ errorMessages.put(new CellReference(cell), UtilProperties.getMessage(resource, "ErrorColCannotEmpty", new Object[] {colNames.get(i)[0]}, locale));
+ foundError = true;
+ continue;
+ } else {
+ cell = row.createCell(i);
+ }
+ }
+ int cellType = cell.getCellType();
+ String cellValue = formatter.formatCellValue(cell);
+ if (UtilValidate.isNotEmpty(cellValue)) {
+ if (cellType == XSSFCell.CELL_TYPE_FORMULA) {
+ cellValue = BigDecimal.valueOf(cell.getNumericCellValue()).setScale(FinAccountHelper.decimals, FinAccountHelper.rounding).toString();
+ report.print(((i == 0)?"":", ") + cellValue, InterfaceReport.FORMAT_NOTE);
+ } else {
+ report.print(((i == 0)?"":", ") + cellValue, InterfaceReport.FORMAT_NOTE);
+ }
+ } else {
+ report.print(((i == 0)?"":","), InterfaceReport.FORMAT_NOTE);
+ }
+ if (((Boolean) colNames.get(i)[2]).booleanValue() && UtilValidate.isEmpty(cellValue)) {
+ report.print(UtilProperties.getMessage(resource, "ErrorColCannotEmpty", new Object[] {colNames.get(i)[0]}, locale), InterfaceReport.FORMAT_WARNING);
+ errorMessages.put(new CellReference(cell), UtilProperties.getMessage(resource, "ErrorColCannotEmpty", new Object[] {colNames.get(i)[0]}, locale));
+ foundError = true;
+ results.add(null);
+ continue;
+ }
+ if (((Boolean) colNames.get(i)[2]).booleanValue() && cellType != (int) colNames.get(i)[1]) {
+ // String warningMessage = "";
+ if ((int) colNames.get(i)[1] == XSSFCell.CELL_TYPE_STRING) {
+ results.add(cellValue);
+ } else if ((int) colNames.get(i)[1] == XSSFCell.CELL_TYPE_NUMERIC) {
+ if (cell.getCellType() != XSSFCell.CELL_TYPE_STRING) {
+ cell.setCellType(XSSFCell.CELL_TYPE_STRING);
+ }
+ try {
+ results.add(BigDecimal.valueOf(Double.parseDouble(cell.getStringCellValue())).setScale(FinAccountHelper.decimals, FinAccountHelper.rounding));
+ } catch (NumberFormatException e) {
+ results.add(null);
+ errorMessages.put(new CellReference(cell), UtilProperties.getMessage(resource, "ErrorParseValueToNumeric", locale));
+ }
+ }
+ } else {
+ if (UtilValidate.isEmpty(cellValue)) {
+ results.add(null);
+ continue;
+ }
+ if ((int) colNames.get(i)[1] == XSSFCell.CELL_TYPE_STRING) {
+ if (cell.getCellType() == XSSFCell.CELL_TYPE_STRING) {
+ results.add(cell.getStringCellValue());
+ } else {
+ results.add(cellValue);
+ }
+ } else if ((int) colNames.get(i)[1] == XSSFCell.CELL_TYPE_NUMERIC) {
+ if (cell.getCellType() == XSSFCell.CELL_TYPE_STRING) {
+ try {
+ results.add(BigDecimal.valueOf(Double.valueOf(cell.getStringCellValue())));
+ } catch (NumberFormatException e) {
+ results.add(null);
+ errorMessages.put(new CellReference(cell), UtilProperties.getMessage(resource, "ErrorParseValueToNumeric", locale));
+ }
+ } else if (cell.getCellType() == XSSFCell.CELL_TYPE_NUMERIC) {
+ try {
+ results.add(BigDecimal.valueOf(cell.getNumericCellValue()).setScale(FinAccountHelper.decimals, FinAccountHelper.rounding));
+ } catch (NumberFormatException e) {
+ results.add(null);
+ errorMessages.put(new CellReference(cell), UtilProperties.getMessage(resource, "ErrorParseValueToNumeric", locale));
+ }
+ } else {
+ try {
+ results.add(BigDecimal.valueOf(Double.valueOf(cellValue)).setScale(FinAccountHelper.decimals, FinAccountHelper.rounding));
+ } catch (NumberFormatException e) {
+ results.add(null);
+ errorMessages.put(new CellReference(cell), UtilProperties.getMessage(resource, "ErrorParseValueToNumeric", locale));
+ }
+ }
+ }
+ }
+ }
+ if (foundError) {
+ return null;
+ }
+ return results;
+ }
+
+ public void setFacilityId(String selectedFacilityId) {
+ this.selectedFacilityId = selectedFacilityId;
+ }
+
+ protected boolean isEmptyRow(XSSFRow row, int size, boolean display) {
+ // check whether this row is empty
+ if (UtilValidate.isEmpty(row)) {
+ report.print(UtilProperties.getMessage(resource, "ExcelEmptyRow", locale), InterfaceReport.FORMAT_NOTE);
+ return true;
+ }
+ boolean isEmptyRow = true;
+ int physicalNumberOfCells = row.getPhysicalNumberOfCells();
+ int i = 0;
+ for (; i < size; i++) {
+ XSSFCell cell = null;
+ if (physicalNumberOfCells > i) {
+ cell = row.getCell(i);
+ }
+ if (cell != null && UtilValidate.isNotEmpty(formatter.formatCellValue(cell)) && UtilValidate.isNotEmpty(formatter.formatCellValue(cell).trim())) {
+ isEmptyRow = false;
+ break;
+ }
+ }
+ if (isEmptyRow) {
+ if (display) {
+ report.print(UtilProperties.getMessage(resource, "ExcelEmptyRow", locale), InterfaceReport.FORMAT_NOTE);
+ }
+ return true;
+ } else if (!isEmptyRow && i > size) {
+ if (display) {
+ report.print(UtilProperties.getMessage(resource, "IgnoreDataOutOfRange", locale), InterfaceReport.FORMAT_NOTE);
+ }
+ return true;
+ }
+ return isEmptyRow;
+ }
+
+ protected abstract int getHeaderRowNo();
+
+
+ public synchronized void endExcelImportHistory(String logFileName, String thruReasonId) {
+ Thread currentThread = Thread.currentThread();
+ String threadName = null;
+ if (currentThread instanceof PricatParseExcelHtmlThread) {
+ threadName = ((PricatParseExcelHtmlThread) currentThread).getUUID().toString();
+ }
+ if (UtilValidate.isEmpty(threadName)) {
+ return;
+ }
+ try {
+ GenericValue historyValue = null;
+ if (sequenceNum < 1L) {
+ historyValue = EntityUtil.getFirst(EntityUtil.filterByDate(delegator.findByAnd("ExcelImportHistory",
+ UtilMisc.toMap("userLoginId", userLoginId, "logFileName", logFileName), UtilMisc.toList("sequenceNum DESC"), false)));
+ } else {
+ historyValue = delegator.findOne("ExcelImportHistory", UtilMisc.toMap("userLoginId", userLoginId, "sequenceNum", (Long) sequenceNum), false);
+ }
+ Timestamp now = UtilDateTime.nowTimestamp();
+ if (UtilValidate.isEmpty(historyValue)) {
+ historyValue = delegator.makeValue("ExcelImportHistory", UtilMisc.toMap("sequenceNum", Long.valueOf(sequenceNum), "userLoginId", userLoginId,
+ "fileName", pricatFile.getName(), "statusId", "EXCEL_IMPORTED", "fromDate", now,
+ "thruDate", now, "threadName", threadName, "logFileName", logFileName));
+ } else {
+ historyValue.set("statusId", "EXCEL_IMPORTED");
+ historyValue.set("thruDate", now);
+ if (pricatFile != null && pricatFile.exists()) {
+ historyValue.set("fileName", pricatFile.getName());
+ }
+ historyValue.set("thruReasonId", thruReasonId);
+ }
+ delegator.createOrStore(historyValue);
+ } catch (GenericEntityException e) {
+ // do nothing
+ }
+ }
+
+ public boolean hasErrorMessages() {
+ return !errorMessages.keySet().isEmpty();
+ }
+
+ /**
+ * Check whether a commented file exists.
+ *
+ * @param request
+ * @param sequenceNum
+ * @return
+ */
+ public static boolean isCommentedExcelExists(HttpServletRequest request, Long sequenceNum) {
+ GenericValue userLogin = (GenericValue) request.getSession().getAttribute("userLogin");
+ if (UtilValidate.isEmpty(sequenceNum) || UtilValidate.isEmpty(userLogin)) {
+ Debug.logError("sequenceNum[" + sequenceNum + "] or userLogin is empty", module);
+ return false;
+ }
+ String userLoginId = userLogin.getString("userLoginId");
+ Delegator delegator = (Delegator) request.getAttribute("delegator");
+ GenericValue historyValue = null;
+ try {
+ historyValue = delegator.findOne("ExcelImportHistory", UtilMisc.toMap("userLoginId", userLoginId, "sequenceNum", Long.valueOf(sequenceNum)), false);
+ } catch (NumberFormatException e) {
+ Debug.logError(e.getMessage(), module);
+ return false;
+ } catch (GenericEntityException e) {
+ Debug.logError(e.getMessage(), module);
+ return false;
+ }
+ if (UtilValidate.isEmpty(historyValue)) {
+ Debug.logError("No ExcelImportHistory value found by sequenceNum[" + sequenceNum + "] and userLoginId[" + userLoginId + "].", module);
+ return false;
+ }
+ File file = FileUtil.getFile(tempFilesFolder + userLoginId + "/" + sequenceNum + ".xlsx");
+ if (file.exists()) {
+ return true;
+ }
+ return false;
+ }
+
+ protected void cleanupLogAndCommentedExcel() {
+ try {
+ report.print(UtilProperties.getMessage(resource, "CLEANUP_LOGANDEXCEL_BEGIN", locale), InterfaceReport.FORMAT_DEFAULT);
+ List<GenericValue> historyValues = delegator.findByAnd("ExcelImportHistory", UtilMisc.toMap("userLoginId", userLoginId), UtilMisc.toList("sequenceNum DESC"), false);
+ if (UtilValidate.isEmpty(historyValues) || historyValues.size() <= HISTORY_MAX_FILENUMBER) {
+ report.print(UtilProperties.getMessage(resource, "HistoryLessThan", new Object[] {String.valueOf(HISTORY_MAX_FILENUMBER)}, locale), InterfaceReport.FORMAT_NOTE);
+ report.println(" ... " + UtilProperties.getMessage(resource, "skipped", locale), InterfaceReport.FORMAT_NOTE);
+ } else {
+ report.print(" ... " + UtilProperties.getMessage(resource, "HistoryEntryToRemove", new Object[] {historyValues.size() - HISTORY_MAX_FILENUMBER}, locale), InterfaceReport.FORMAT_NOTE);
+ List<GenericValue> valuesToRemove = new ArrayList<GenericValue>();
+ for (int i = HISTORY_MAX_FILENUMBER; i < historyValues.size(); i++) {
+ GenericValue historyValue = historyValues.get(i);
+ valuesToRemove.add(historyValue);
+ File excelFile = FileUtil.getFile(tempFilesFolder + userLoginId + "/" + historyValue.getLong("sequenceNum") + ".xlsx");
+ if (excelFile.exists()) {
+ try {
+ excelFile.delete();
+ } catch (SecurityException e) {
+ Debug.logError(e.getMessage(), module);
+ report.print(e.getMessage(), InterfaceReport.FORMAT_ERROR);
+ }
+ }
+ File logFile = FileUtil.getFile(tempFilesFolder + userLoginId + "/" + historyValue.getLong("sequenceNum") + ".log");
+ if (logFile.exists()) {
+ try {
+ logFile.delete();
+ } catch (SecurityException e) {
+ Debug.logError(e.getMessage(), module);
+ report.print(e.getMessage(), InterfaceReport.FORMAT_ERROR);
+ }
+ }
+ }
+ delegator.removeAll(valuesToRemove);
+ report.println(" ... " + UtilProperties.getMessage(resource, "ok", locale), InterfaceReport.FORMAT_OK);
+ }
+ report.println();
+ } catch (GenericEntityException e) {
+ Debug.logError(e.getMessage(), module);
+ }
+ }
+}
Added: ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/pricat/InterfacePricatParser.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/pricat/InterfacePricatParser.java?rev=1770621&view=auto
==============================================================================
--- ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/pricat/InterfacePricatParser.java (added)
+++ ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/pricat/InterfacePricatParser.java Mon Nov 21 08:07:57 2016
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * 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.ofbiz.pricat;
+
+import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.poi.xssf.usermodel.XSSFRow;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.apache.ofbiz.base.util.UtilMisc;
+import org.apache.ofbiz.base.util.UtilProperties;
+import org.apache.ofbiz.entity.transaction.GenericTransactionException;
+
+/**
+ * Interface of pricat parser.
+ *
+ */
+public interface InterfacePricatParser {
+
+ public static final String PARSE_EXCEL = "parse_excel";
+
+ public static final String CONFIRM = "confirm_action";
+
+ public static final String[] messageLabels = new String[] {"FORMAT_DEFAULT", "FORMAT_WARNING", "FORMAT_HEADLINE", "FORMAT_NOTE", "FORMAT_OK", "FORMAT_ERROR", "FORMAT_THROWABLE"};
+
+ public static final List<String> messages = Collections.unmodifiableList(Arrays.asList(messageLabels));
+
+ public static final String tempFilesFolder = "runtime/pricat/";
+
+ public static final String FileDateTimePattern = "yyyyMMddHHmmss";
+
+ public static final String defaultColorName = "DefaultColor";
+
+ public static final String defaultDimensionName = "DefaultDimension";
+
+ public static final String defaultCategoryName = "DefaultCategory";
+
+ public static final String EXCEL_TEMPLATE_TYPE = "excelTemplateType";
+
+ public static final String FACILITY_ID = "facilityId";
+
+ public static final String resource = "PricatUiLabels";
+
+ public static final String PRICAT_FILE = "__PRICAT_FILE__";
+
+ public static final String DEFAULT_PRICAT_TYPE = "ApacheOFBiz";
+
+ public static final Map<String, String> PricatTypeLabels = UtilMisc.toMap(DEFAULT_PRICAT_TYPE, "ApacheOFBizPricatTemplate", "SamplePricat", "SamplePricatTemplate");
+
+ public static final int HISTORY_MAX_FILENUMBER = UtilProperties.getPropertyAsInteger("pricat.properties", "pricat.history.max.filenumber", 20);
+
+ abstract void parsePricatExcel();
+
+ public void writeCommentsToFile(XSSFWorkbook workbook, XSSFSheet sheet);
+
+ public void initBasicConds(List<String> orgPartyIds);
+
+ public boolean existsCurrencyId(XSSFSheet sheet);
+
+ abstract void parseRowByRow(XSSFSheet sheet);
+
+ abstract boolean parseCellContentsAndStore(XSSFRow row, List<Object> cellContents) throws GenericTransactionException;
+
+ public Map<String, Object> updateSkuPrice(String skuId, String ownerPartyId, BigDecimal memberPrice);
+
+ abstract String updateSku(XSSFRow row, String productId, String ownerPartyId, String facilityId, String barcode, BigDecimal inventory,
+ String colorId, String color, String dimensionId, String dimension, BigDecimal listPrice, BigDecimal averageCost);
+
+ public Map<String, Object> updateColorAndDimension(String productId, String ownerPartyId, String color, String dimension);
+
+ public Map<String, Object> getDimensionIds(String productId, String ownerPartyId, String dimension);
+
+ public Map<String, Object> getColorIds(String productId, String ownerPartyId, String color);
+
+ abstract String getProductId(XSSFRow row, String brandId, String modelName, String productName, String productCategoryId, String ownerPartyId, BigDecimal listPrice);
+
+ public String getBrandId(String brandName, String ownerPartyId);
+
+ abstract Object getCellContent(List<Object> cellContents, String colName);
+
+ abstract String getProductCategoryId(List<Object> cellContents, String ownerPartyId);
+
+ abstract boolean isFacilityOk(XSSFRow row, String facilityName, String facilityId);
+
+ abstract List<Object> getCellContents(XSSFRow row, List<Object[]> colNames, int size);
+
+ abstract boolean isTableHeaderMatched(XSSFSheet sheet);
+
+ abstract boolean isVersionSupported(XSSFSheet sheet);
+
+ abstract boolean containsDataRows(XSSFSheet sheet);
+
+ public boolean isNumOfSheetsOK(XSSFWorkbook workbook);
+
+ abstract void setFacilityId(String selectedFacilityId);
+
+ public void endExcelImportHistory(String logFileName, String thruReasonId);
+
+ public boolean hasErrorMessages();
+}
Added: ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/pricat/PricatEvents.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/pricat/PricatEvents.java?rev=1770621&view=auto
==============================================================================
--- ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/pricat/PricatEvents.java (added)
+++ ofbiz/trunk/specialpurpose/pricat/src/main/java/org/apache/ofbiz/pricat/PricatEvents.java Mon Nov 21 08:07:57 2016
@@ -0,0 +1,193 @@
+/*******************************************************************************
+ * 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.ofbiz.pricat;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URLEncoder;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+import org.jdom.JDOMException;
+import org.apache.ofbiz.base.location.ComponentLocationResolver;
+import org.apache.ofbiz.base.util.Debug;
+import org.apache.ofbiz.base.util.FileUtil;
+import org.apache.ofbiz.base.util.UtilHttp;
+import org.apache.ofbiz.base.util.UtilMisc;
+import org.apache.ofbiz.base.util.UtilProperties;
+import org.apache.ofbiz.base.util.UtilValidate;
+import org.apache.ofbiz.entity.Delegator;
+import org.apache.ofbiz.entity.GenericEntityException;
+import org.apache.ofbiz.entity.GenericValue;
+import org.apache.ofbiz.pricat.AbstractPricatParser;
+import org.apache.ofbiz.pricat.InterfacePricatParser;
+import org.apache.ofbiz.pricat.PricatParseExcelHtmlThread;
+
+public class PricatEvents {
+
+ public static final String module = PricatEvents.class.getName();
+
+ public static final String PricatLatestVersion = UtilProperties.getPropertyValue("pricat", "pricat.latest.version", "V1.1");
+
+ public static final String PricatFileName = "PricatTemplate_" + PricatLatestVersion + ".xlsx";
+
+ public static final String PricatPath = "component://pricat/webapp/pricat/downloads/";
+
+ /**
+ * Download excel template.
+ *
+ * @param request
+ * @param response
+ * @return
+ * @throws IOException
+ * @throws JDOMException
+ */
+ public static String downloadExcelTemplate(HttpServletRequest request, HttpServletResponse response) {
+ String templateType = request.getParameter("templateType");
+ if (UtilValidate.isEmpty(templateType)) {
+ return "error";
+ }
+ try {
+ String path = ComponentLocationResolver.getBaseLocation(PricatPath).toString();
+ String fileName = null;
+ if ("pricatExcelTemplate".equals(templateType)) {
+ fileName = PricatFileName;
+ }
+ if (UtilValidate.isEmpty(fileName)) {
+ return "error";
+ }
+ Path file = Paths.get(path + fileName);
+ byte[] bytes = Files.readAllBytes(file);
+ UtilHttp.streamContentToBrowser(response, bytes, "application/octet-stream", URLEncoder.encode(fileName, "UTF-8"));
+ } catch (MalformedURLException e) {
+ Debug.logError(e.getMessage(), module);
+ return "error";
+ } catch (IOException e) {
+ Debug.logError(e.getMessage(), module);
+ return "error";
+ }
+ return "success";
+ }
+
+ /**
+ * Upload a pricat.
+ */
+ public static String pricatUpload(HttpServletRequest request, HttpServletResponse response) {
+ boolean isMultiPart = ServletFileUpload.isMultipartContent(request);
+ if (isMultiPart) {
+ return "parse_pricat";
+ } else {
+ String action = request.getParameter("action");
+ if (UtilValidate.isNotEmpty(action) && "downloadPricat".equals(action)) {
+ String sequenceNumString = (String) request.getParameter("sequenceNum");
+ long sequenceNum = -1;
+ if (UtilValidate.isNotEmpty(sequenceNumString)) {
+ try {
+ sequenceNum = Long.valueOf(sequenceNumString);
+ } catch (NumberFormatException e) {
+ // do nothing
+ }
+ }
+ String originalPricatFileName = (String) request.getSession().getAttribute(PricatParseExcelHtmlThread.PRICAT_FILE);
+ String pricatFileName = originalPricatFileName;
+ if (sequenceNum > 0 && AbstractPricatParser.isCommentedExcelExists(request, sequenceNum)) {
+ GenericValue userLogin = (GenericValue) request.getSession().getAttribute("userLogin");
+ String userLoginId = userLogin.getString("userLoginId");
+ pricatFileName = InterfacePricatParser.tempFilesFolder + userLoginId + "/" + sequenceNum + ".xlsx";
+ }
+ if (UtilValidate.isNotEmpty(pricatFileName) && UtilValidate.isNotEmpty(originalPricatFileName)) {
+ try {
+ Path path = Paths.get(pricatFileName);
+ byte[] bytes = Files.readAllBytes(path);
+ path = Paths.get(originalPricatFileName);
+ UtilHttp.streamContentToBrowser(response, bytes, "application/octet-stream", URLEncoder.encode(path.getName(path.getNameCount() - 1).toString(), "UTF-8"));
+ } catch (MalformedURLException e) {
+ Debug.logError(e.getMessage(), module);
+ return "error";
+ } catch (IOException e) {
+ Debug.logError(e.getMessage(), module);
+ return "error";
+ }
+ request.getSession().removeAttribute(PricatParseExcelHtmlThread.PRICAT_FILE);
+ return "download";
+ }
+ }
+ }
+ return "success";
+ }
+
+ /**
+ * Download commented excel file after it's parsed.
+ *
+ * @param request
+ * @param response
+ * @return
+ * @throws IOException
+ * @throws JDOMException
+ */
+ public static String downloadCommentedExcel(HttpServletRequest request, HttpServletResponse response) {
+ String sequenceNum = request.getParameter("sequenceNum");
+ GenericValue userLogin = (GenericValue) request.getSession().getAttribute("userLogin");
+ if (UtilValidate.isEmpty(sequenceNum) || UtilValidate.isEmpty(userLogin)) {
+ Debug.logError("sequenceNum[" + sequenceNum + "] or userLogin is empty", module);
+ return "error";
+ }
+ String userLoginId = userLogin.getString("userLoginId");
+ Delegator delegator = (Delegator) request.getAttribute("delegator");
+ GenericValue historyValue = null;
+ try {
+ historyValue = delegator.findOne("ExcelImportHistory", UtilMisc.toMap("userLoginId", userLoginId, "sequenceNum", Long.valueOf(sequenceNum)), false);
+ } catch (NumberFormatException e) {
+ Debug.logError(e.getMessage(), module);
+ return "error";
+ } catch (GenericEntityException e) {
+ Debug.logError(e.getMessage(), module);
+ return "error";
+ }
+ if (UtilValidate.isEmpty(historyValue)) {
+ Debug.logError("No ExcelImportHistory value found by sequenceNum[" + sequenceNum + "] and userLoginId[" + userLoginId + "].", module);
+ return "error";
+ }
+ String fileName = historyValue.getString("fileName");
+ if (UtilValidate.isEmpty(fileName)) {
+ fileName = sequenceNum + ".xlsx";
+ }
+ try {
+ File file = FileUtil.getFile(InterfacePricatParser.tempFilesFolder + userLoginId + "/" + sequenceNum + ".xlsx");
+ if (file.exists()) {
+ Path path = Paths.get(file.getPath());
+ byte[] bytes = Files.readAllBytes(path);
+ UtilHttp.streamContentToBrowser(response, bytes, "application/octet-stream", URLEncoder.encode(fileName, "UTF-8"));
+ }
+ } catch (MalformedURLException e) {
+ Debug.logError(e.getMessage(), module);
+ return "error";
+ } catch (IOException e) {
+ Debug.logError(e.getMessage(), module);
+ return "error";
+ }
+ return "success";
+ }
+}