/* * Copyright (c) 2005-2016 Vincent Vandenschrick. All rights reserved. * * This file is part of the Jspresso framework. * * Jspresso is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Jspresso is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Jspresso. If not, see <http://www.gnu.org/licenses/>. */ package org.jspresso.framework.util.freemarker; import java.util.HashMap; import java.util.List; import java.util.Map; import freemarker.template.SimpleScalar; import freemarker.template.TemplateMethodModelEx; import freemarker.template.TemplateModel; import freemarker.template.TemplateModelException; /** * Reduces the SQL identifiers to apply a maximum length. * * @author Vincent Vandenschrick */ @SuppressWarnings("rawtypes") public class ReduceSqlName implements TemplateMethodModelEx { private static final String WORD_SEP = "_"; private final int maxSize; private final Map<String, String> shortened; private final DedupSqlName dedupper; /** * Constructs a new {@code ReduceSqlName} instance. * * @param maxSize the maximum size of the identifiers. * means no * limit. * @param dedupSqlName the dedup sql name */ public ReduceSqlName(int maxSize, DedupSqlName dedupSqlName) { this.maxSize = maxSize; shortened = new HashMap<>(); dedupper = dedupSqlName; } /** * Reduces an input string. * <p> * {@inheritDoc} */ @Override public TemplateModel exec(List arguments) throws TemplateModelException { try { String sqlNameToReduce = arguments.get(0).toString(); String mandatorySuffix = ""; if (arguments.size() > 1) { mandatorySuffix = arguments.get(1).toString(); } return new SimpleScalar(reduceToMaxSize(sqlNameToReduce, mandatorySuffix)); } catch (Exception ex) { throw new TemplateModelException("Could execute reduceSqlName method.", ex); } } private String reduceToMaxSize(String sqlColumnName, String mandatorySuffix) { String shortenedKey = sqlColumnName + mandatorySuffix; int size = maxSize; if (mandatorySuffix.length() > 0) { size -= mandatorySuffix.length(); } if (size <= 0 || sqlColumnName.length() <= size) { return sqlColumnName + mandatorySuffix; } if (shortened.containsKey(shortenedKey)) { return shortened.get(shortenedKey); } String[] splitted = sqlColumnName.split(WORD_SEP); int charsPerSection = (size / splitted.length) - 1; StringBuilder reduced = new StringBuilder(); if (charsPerSection > 0) { int remainingExtraChars = 0; for (String section : splitted) { if (section.length() < charsPerSection) { remainingExtraChars += (charsPerSection - section.length()); } } for (String section : splitted) { if (section.length() <= charsPerSection) { reduced.append(section); } else { int extraChars = 0; if (remainingExtraChars > 0) { extraChars = Math.min(remainingExtraChars, section.length() - charsPerSection); remainingExtraChars -= extraChars; } reduced.append(section.substring(0, charsPerSection + extraChars)); } reduced.append(WORD_SEP); } } else { reduced.append(sqlColumnName.substring(0, size - 2)).append(WORD_SEP); } String reducedAsString = reduced.toString(); reducedAsString = dedupper.dedup(reducedAsString); shortened.put(shortenedKey, reducedAsString + mandatorySuffix); return reducedAsString + mandatorySuffix; } }