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"; + } +} |
Free forum by Nabble | Edit this page |