/*
* Copyright 2012 PRODYNA AG
*
* Licensed under the Eclipse Public License (EPL), Version 1.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.opensource.org/licenses/eclipse-1.0.php or
* http://www.nabucco.org/License.html
*
* 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.nabucco.framework.common.dynamiccode.impl.service.util;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import org.nabucco.framework.base.facade.datatype.code.CodePath;
import org.nabucco.framework.base.facade.exception.persistence.PersistenceException;
import org.nabucco.framework.base.facade.exception.service.SearchException;
import org.nabucco.framework.base.impl.service.maintain.NabuccoQuery;
import org.nabucco.framework.base.impl.service.maintain.PersistenceManager;
import org.nabucco.framework.common.dynamiccode.facade.datatype.DynamicCodeCode;
import org.nabucco.framework.common.dynamiccode.impl.service.common.cache.DynamicCodeCache;
/**
* CodePathResolver
* <p/>
* Utility class for resolving codes by code path.
*
* @author Nicolas Moser, PRODYNA AG
*/
public class CodePathResolver {
private static final Pattern PATTERN = Pattern.compile("\\.");
private PersistenceManager manager;
/**
* Creates a new {@link CodePathResolver} instance.
*
* @param manager
* the persistence manager
*/
public CodePathResolver(PersistenceManager manager) {
this.manager = manager;
}
/**
* Resolves the codes for a given code path.
*
* @param path
* the code path to resolve
*
* @throws SearchException
* when the search did not finish normally
*/
public Set<DynamicCodeCode> resolve(CodePath path) throws SearchException {
Set<DynamicCodeCode> resultSet = new HashSet<DynamicCodeCode>();
if (path == null || path.getValue() == null) {
throw new IllegalArgumentException("Cannot search for code path [null].");
}
Collection<DynamicCodeCode> codes = DynamicCodeCache.retrieveFromCache(path);
if (codes != null) {
return new HashSet<DynamicCodeCode>(codes);
}
String[] groups = PATTERN.split(path.getValue());
if (groups.length == 0) {
throw new IllegalArgumentException("Cannot search for code path [].");
}
String queryString = this.createQuery(groups.length);
try {
NabuccoQuery<DynamicCodeCode> query = this.manager.createQuery(queryString);
for (int i = 0; i < groups.length; i++) {
String group = groups[i];
if (group == null || group.isEmpty()) {
throw new IllegalArgumentException("Cannot search for code group [].");
}
query.setParameter("name" + i, group);
}
List<DynamicCodeCode> resultList = query.getResultList();
resultSet.addAll(resultList);
} catch (PersistenceException pe) {
throw new SearchException("Error searching for DynamicCodeCode.", pe);
}
DynamicCodeCache.sendToCache(path, resultSet);
return resultSet;
}
/**
* Create the dynamic query for code path resolving.
*
* @param groupCount
* the amount of code group tokens
*
* @return the query string
*/
private String createQuery(int groupCount) {
StringBuilder queryString = new StringBuilder();
queryString.append("select c from DynamicCodeCodeGroup g");
for (int i = 0; i < groupCount; i++) {
if (i == 0) {
queryString.append(i);
} else {
queryString.append(" inner join g" + (i - 1) + ".codeGroupListJPA g" + i);
}
}
queryString.append(" inner join g" + (groupCount - 1) + ".codeListJPA c");
queryString.append(" where ");
for (int i = 0; i < groupCount; i++) {
if (i != 0) {
queryString.append(" and ");
}
queryString.append("g" + i + ".name.value = :name" + i);
}
return queryString.toString();
}
}