diff --git a/src/main/java/info/bukova/isspst/Constants.java b/src/main/java/info/bukova/isspst/Constants.java index 8630c523..c253f435 100644 --- a/src/main/java/info/bukova/isspst/Constants.java +++ b/src/main/java/info/bukova/isspst/Constants.java @@ -14,6 +14,7 @@ import info.bukova.isspst.data.TripBill; import info.bukova.isspst.data.TripRequirement; import info.bukova.isspst.reporting.Report; import info.bukova.isspst.reporting.ReportMapping; +import info.bukova.isspst.services.FullTextService; import info.bukova.isspst.services.addressbook.AdbService; import info.bukova.isspst.services.buildings.BuildingService; import info.bukova.isspst.services.invoicing.InvoicingService; @@ -81,6 +82,7 @@ public class Constants { public final static String MOD_APPROVED = "APPROVED"; public final static String MOD_ORDER = "ORDER"; public final static String MOD_INVOICING = "INVOICING"; + public final static String MOD_SEARCH = "SEARCH"; public final static Module MODULES[] = { new Module(MOD_USERS, "Uživatelé", UserService.class), new Module(MOD_PERMISSIONS, "Práva", RoleService.class), @@ -96,7 +98,9 @@ public class Constants { new Module(MOD_TRIPBILL, "Cestovní příkazy", TripBillService.class), new Module(MOD_APPROVED, "Schválené položky požadavků", ApprovedService.class), new Module(MOD_ORDER, "Objednávky", OrderService.class), - new Module(MOD_INVOICING, "Fakturace požadavků", InvoicingService.class) }; + new Module(MOD_INVOICING, "Fakturace požadavků", InvoicingService.class), + new Module(MOD_SEARCH, "Fulltextové vyhledávání", FullTextService.class, true, false), + }; public final static String PERM_APPROVE = "PERM_APPROVE"; public final static String PERM_SHOW_WORKGROUP_REQ = "PERM_SHOW_WORKGROUP_REQ"; @@ -104,6 +108,7 @@ public class Constants { public final static String PERM_SHOW_ALL_REQ = "PERM_SHOW_ALL_REQ"; public final static String PERM_EDIT_NEW = "PERM_EDIT_NEW"; public final static String PERM_EDIT_OWN = "PERM_EDIT_OWN"; + public final static String PERM_SEARCH = "PERM_SEARCH"; public final static Permission SPECIAL_PERMISSIONS[] = { new Permission(PERM_EDIT_NEW, "Upravit neschválené", MOD_REQUIREMENTS, PermissionType.GLOBAL), @@ -117,6 +122,8 @@ public class Constants { new Permission(PERM_SHOW_CENTRE_REQ, "Zobrazení požadavků střediska", MOD_TRIPREQUIREMENTS, PermissionType.CENTRE), new Permission(PERM_SHOW_ALL_REQ, "Zobrazení všech požadavků", MOD_TRIPREQUIREMENTS, PermissionType.GLOBAL), new Permission(PERM_APPROVE, "Schválení", MOD_TRIPREQUIREMENTS, PermissionType.WORKGROUP), + + new Permission(PERM_SEARCH, "Vyhledávat", MOD_SEARCH, PermissionType.GLOBAL), }; public final static String DYNAMIC_REPORT_NAME = "Tabulková sestava"; diff --git a/src/main/java/info/bukova/isspst/Module.java b/src/main/java/info/bukova/isspst/Module.java index eeda73e8..5a7c41e2 100644 --- a/src/main/java/info/bukova/isspst/Module.java +++ b/src/main/java/info/bukova/isspst/Module.java @@ -1,10 +1,18 @@ package info.bukova.isspst; import info.bukova.isspst.reporting.Report; +import info.bukova.isspst.services.AbstractService; +import info.bukova.isspst.services.ModuleNotActiveException; import java.util.ArrayList; import java.util.List; +/** + * @author Pepa Rokos + * + * Třída reprezentuje informace o modulu (agendě). + * + */ public class Module { private String id; @@ -22,6 +30,12 @@ public class Module { this.serviceClass = serviceClass; } + /** + * + * @param id identifikátor modulu + * @param name jméno zobrazované v aplikaci + * @param serviceClass servisní třída + */ public Module(String id, String name, Class serviceClass) { this.id = id; this.name = name; @@ -31,11 +45,24 @@ public class Module { active = true; } + /** + * @param id identifikátor modulu + * @param name jméno zobrazované v aplikaci + * @param serviceClass servisní třída + * @param active příznak, jestli je modul aktivní + */ public Module(String id, String name, Class serviceClass, boolean active) { this(id, name, serviceClass); this.active = active; } + /** + * @param id identifikátor modulu + * @param name jméno zobrazované v aplikaci + * @param serviceClass servisní třída + * @param active příznak, jestli je modul aktivní. + * @param defaultPermissions příznak určující jestli modul kontroluje výchozí práva (čtení, zápis, modifikace, mazání) + */ public Module(String id, String name, Class serviceClass, boolean active, boolean defaultPermissions) { this(id, name, serviceClass, active); this.defaultPermissions = defaultPermissions; @@ -65,6 +92,12 @@ public class Module { this.reports.add(report); } + /** + * Pokud je true, modul kontroluje výchozí práva (čtení, zápis, modifikace, mazání). Má vliv + * na generování formulářů v nastavení práv. + * + * @return výchozí práva. Default true + */ public boolean isDefaultPermissions() { return defaultPermissions; } @@ -73,6 +106,13 @@ public class Module { this.defaultPermissions = defaultPermissions; } + /** + * Určuje, zda je modul aktivní. Neaktivní moduly nejsou viditelné v UI. Při pokusu o přístup přímo přes URL + * se generuje výjimka {@link ModuleNotActiveException}. Pokud servisní třída modulu nedědí z {@link AbstractService}, + * musí se implementovat kontrola aktivity do příslušné třídy. + * + * @return aktivita. Default true + */ public boolean isActive() { return active; } diff --git a/src/main/java/info/bukova/isspst/services/FullTextService.java b/src/main/java/info/bukova/isspst/services/FullTextService.java index 2336c0ab..7217663b 100644 --- a/src/main/java/info/bukova/isspst/services/FullTextService.java +++ b/src/main/java/info/bukova/isspst/services/FullTextService.java @@ -2,10 +2,41 @@ package info.bukova.isspst.services; import java.util.List; +import org.hibernate.search.annotations.Field; +import org.hibernate.search.annotations.Indexed; + +/** + * @author Pepa Rokos + * + * Rozhraní služby fulltextového vyhledávání + * + */ public interface FullTextService { + /** + * Přegeneruje fulltextový index. + */ public void reindex(); + + + /** + * Vyhledává entity zadané třídy. Třída entity musí být anotovaná {@link Indexed} + * + * @param entityClass třída entity k vyhledání + * @param fields property entity kde se bude vyhledávat. Musí být anotované {@link Field} + * @param word vyhledávaný výraz + * @return list odpovídajících entit + */ public List search(Class entityClass, String[] fields, String word); + + + /** + * Globální vyhledávání ve všech entitách, jejichš třídy jsou anotované {@link Indexed} a + * property {@link Field} + * + * @param word vyhledávaný výraz + * @return list odpovídajících entit + */ public List globalSearch(String word); } diff --git a/src/main/java/info/bukova/isspst/services/FullTextServiceImpl.java b/src/main/java/info/bukova/isspst/services/FullTextServiceImpl.java index 12018c4b..12dee947 100644 --- a/src/main/java/info/bukova/isspst/services/FullTextServiceImpl.java +++ b/src/main/java/info/bukova/isspst/services/FullTextServiceImpl.java @@ -1,5 +1,6 @@ package info.bukova.isspst.services; +import info.bukova.isspst.ModuleUtils; import info.bukova.isspst.dao.QueryDao; import info.bukova.isspst.data.BaseData; import info.bukova.isspst.data.User; @@ -24,6 +25,7 @@ import org.hibernate.search.query.dsl.QueryBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.transaction.annotation.Transactional; public class FullTextServiceImpl implements FullTextService { @@ -55,7 +57,9 @@ public class FullTextServiceImpl implements FullTextService { @Override @Transactional + @PreAuthorize("hasPermission(this, 'PERM_SEARCH')") public List search(Class entityClass, String[] fields, String word) { + checkActivity(); FullTextSession session = Search.getFullTextSession(queryDao.getSession()); QueryBuilder qb = session.getSearchFactory().buildQueryBuilder().forEntity(entityClass).get(); @@ -67,7 +71,9 @@ public class FullTextServiceImpl implements FullTextService { @Override @Transactional + @PreAuthorize("hasPermission(this, 'PERM_SEARCH')") public List globalSearch(String word) { + checkActivity(); List result = new ArrayList(); for (Class clazz : classesForSearch()) { @@ -83,6 +89,12 @@ public class FullTextServiceImpl implements FullTextService { return result; } + private void checkActivity() { + if (!ModuleUtils.getModule(this.getClass()).isActive()) { + throw new ModuleNotActiveException(); + } + } + private List> classesForSearch() { if (classesForSearch != null) { return classesForSearch; diff --git a/src/main/java/info/bukova/isspst/ui/search/AbstractResultTransformer.java b/src/main/java/info/bukova/isspst/ui/search/AbstractResultTransformer.java index e2b5f8f3..e619a58a 100644 --- a/src/main/java/info/bukova/isspst/ui/search/AbstractResultTransformer.java +++ b/src/main/java/info/bukova/isspst/ui/search/AbstractResultTransformer.java @@ -2,7 +2,14 @@ package info.bukova.isspst.ui.search; import info.bukova.isspst.EntityUrlResolver; import info.bukova.isspst.data.BaseData; +import info.bukova.isspst.data.DataModel; +/** + * @author Pepa Rokos + * + * Třída obecného transformačního objektu. Do výsledku nastaví property z rozhraní {@link DataModel}, které implementují všechny entity. + * + */ public abstract class AbstractResultTransformer implements ResultTransformer { protected EntityUrlResolver urlResolver; @@ -27,6 +34,12 @@ public abstract class AbstractResultTransformer implements ResultTransformer { return result; } + /** + * Další transformace v závislosti na konkrétní třídě přdané entity + * + * @param object entita k transformaci + * @param result výsledný transformovaný objekt + */ protected abstract void transform(Object object, SearchResult result); @Override diff --git a/src/main/java/info/bukova/isspst/ui/search/OrderResultTransformer.java b/src/main/java/info/bukova/isspst/ui/search/OrderResultTransformer.java index c2d2cebf..b3e1b7fe 100644 --- a/src/main/java/info/bukova/isspst/ui/search/OrderResultTransformer.java +++ b/src/main/java/info/bukova/isspst/ui/search/OrderResultTransformer.java @@ -1,5 +1,6 @@ package info.bukova.isspst.ui.search; +import info.bukova.isspst.StringUtils; import info.bukova.isspst.data.Order; public class OrderResultTransformer extends AbstractResultTransformer implements ResultTransformer { @@ -7,8 +8,8 @@ public class OrderResultTransformer extends AbstractResultTransformer implements @Override protected void transform(Object object, SearchResult result) { Order order = (Order)object; - result.setRecordName("Objednávka: " + order.getNumser()); - result.setDescription(order.getDescription() + ", dodavatel: " + order.getSuplier().getCompany()); + result.setRecordName(StringUtils.localize("Order") + ": " + order.getNumser()); + result.setDescription(order.getDescription() + ", " + StringUtils.localize("Supplier") + ": " + order.getSuplier().getCompany()); } } diff --git a/src/main/java/info/bukova/isspst/ui/search/RequirementResultTransformer.java b/src/main/java/info/bukova/isspst/ui/search/RequirementResultTransformer.java index 0062bd5f..c39e00d3 100644 --- a/src/main/java/info/bukova/isspst/ui/search/RequirementResultTransformer.java +++ b/src/main/java/info/bukova/isspst/ui/search/RequirementResultTransformer.java @@ -1,5 +1,7 @@ package info.bukova.isspst.ui.search; +import info.bukova.isspst.Constants; +import info.bukova.isspst.StringUtils; import info.bukova.isspst.data.Requirement; public class RequirementResultTransformer extends AbstractResultTransformer implements ResultTransformer { @@ -7,7 +9,15 @@ public class RequirementResultTransformer extends AbstractResultTransformer impl @Override protected void transform(Object object, SearchResult result) { Requirement req = (Requirement)object; - result.setRecordName("Požadavek na nákup/službu: " + req.getNumser()); + String moduleName; + + if (req.getKind() != null && req.getKind().equals(Constants.REQ_TYPE_SERVICES)) { + moduleName = StringUtils.localize("ServiceRequirement"); + } else { + moduleName = StringUtils.localize("MaterialRequirement"); + } + + result.setRecordName(moduleName + ": " + req.getNumser()); result.setDescription(req.getDescription()); } diff --git a/src/main/java/info/bukova/isspst/ui/search/ResultTransformer.java b/src/main/java/info/bukova/isspst/ui/search/ResultTransformer.java index 32e0d053..fcf88204 100644 --- a/src/main/java/info/bukova/isspst/ui/search/ResultTransformer.java +++ b/src/main/java/info/bukova/isspst/ui/search/ResultTransformer.java @@ -2,9 +2,29 @@ package info.bukova.isspst.ui.search; import info.bukova.isspst.EntityUrlResolver; +/** + * @author Pepa Rokos + * + * Rozhraní transformačního objektu výsledků fulltextového vyhledávání. Z vyhledaných entit potřebujeme na UI + * objekty třídy {@link SearchResult}. + * + */ public interface ResultTransformer { + /** + * Transformuje entitu na {@link SearchResult} + * + * @param object entita k transformaci + * @return objekt {@link SearchResult} + */ public SearchResult transformObject(Object object); + + + /** + * Nastaví objekt vyhodnocovače URL záznamu, aby bylo možné generovat URL pro přímý přístup do příslušné agendy a vystavení kurzoru v gridu. + * + * @param resolver vyhodnocovač URL + */ public void setUrlResolver(EntityUrlResolver resolver); } diff --git a/src/main/java/info/bukova/isspst/ui/search/SearchForm.java b/src/main/java/info/bukova/isspst/ui/search/SearchForm.java index 81f8c16a..24b3ae64 100644 --- a/src/main/java/info/bukova/isspst/ui/search/SearchForm.java +++ b/src/main/java/info/bukova/isspst/ui/search/SearchForm.java @@ -1,17 +1,14 @@ package info.bukova.isspst.ui.search; +import info.bukova.isspst.UrlResolverHolder; +import info.bukova.isspst.services.FullTextService; + import java.util.List; import org.zkoss.bind.annotation.Command; import org.zkoss.bind.annotation.NotifyChange; import org.zkoss.zk.ui.select.annotation.WireVariable; -import info.bukova.isspst.UrlResolverHolder; -import info.bukova.isspst.data.BaseData; -import info.bukova.isspst.data.Requirement; -import info.bukova.isspst.data.TripRequirement; -import info.bukova.isspst.services.FullTextService; - public class SearchForm { @WireVariable @@ -33,9 +30,7 @@ public class SearchForm { return; } - //String[] fields = {"items.textItem", "description"}; List result = fulltextService.globalSearch(keyWord); - //List result = fulltextService.search(Requirement.class, fields, keyWord); SearchListTransformer srt = new SearchListTransformer(urlResolverHolder); results = srt.transform(result); diff --git a/src/main/java/info/bukova/isspst/ui/search/SearchListTransformer.java b/src/main/java/info/bukova/isspst/ui/search/SearchListTransformer.java index e357c717..8843fd01 100644 --- a/src/main/java/info/bukova/isspst/ui/search/SearchListTransformer.java +++ b/src/main/java/info/bukova/isspst/ui/search/SearchListTransformer.java @@ -5,6 +5,12 @@ import info.bukova.isspst.UrlResolverHolder; import java.util.ArrayList; import java.util.List; +/** + * @author Pepa Rokos + * + * Transformuje list různých entit na list objektů třídy {@link SearchResult} + * + */ public class SearchListTransformer { private UrlResolverHolder urlResolverHolder; @@ -15,6 +21,9 @@ public class SearchListTransformer { + /** + * @param urlResolverHolder kontajner vyhodnocovačů URL (objekt se konfiguruje přes Spring context) + */ public SearchListTransformer(UrlResolverHolder urlResolverHolder) { super(); this.urlResolverHolder = urlResolverHolder; diff --git a/src/main/java/info/bukova/isspst/ui/search/SearchResult.java b/src/main/java/info/bukova/isspst/ui/search/SearchResult.java index f3ca3542..34f4e7bc 100644 --- a/src/main/java/info/bukova/isspst/ui/search/SearchResult.java +++ b/src/main/java/info/bukova/isspst/ui/search/SearchResult.java @@ -4,6 +4,12 @@ import info.bukova.isspst.data.User; import java.util.Date; +/** + * @author Pepa Rokos + * + * Třída výsledků fulltextového vyhledávání. Na property objektu této třídy jsou bindovány prvky ze zobrazovacího ZUL souboru. + * + */ public class SearchResult { private String recordName; diff --git a/src/main/java/info/bukova/isspst/ui/search/TransformerFactory.java b/src/main/java/info/bukova/isspst/ui/search/TransformerFactory.java index 046cc542..b49aa58a 100644 --- a/src/main/java/info/bukova/isspst/ui/search/TransformerFactory.java +++ b/src/main/java/info/bukova/isspst/ui/search/TransformerFactory.java @@ -5,8 +5,20 @@ import info.bukova.isspst.data.Requirement; import info.bukova.isspst.data.TripBill; import info.bukova.isspst.data.TripRequirement; +/** + * @author Pepa Rokos + * + * Tovární třída transformačních objektů + * + */ public class TransformerFactory { + /** + * Vrací transformační objekt pro předanou entitu + * + * @param object entita k transformaci + * @return transformační objekt + */ public static ResultTransformer transformerFor(Object object) { if (object instanceof TripBill) { return new TripBillTransformer(); diff --git a/src/main/java/info/bukova/isspst/ui/search/TripBillTransformer.java b/src/main/java/info/bukova/isspst/ui/search/TripBillTransformer.java index 8b636959..fd3dc454 100644 --- a/src/main/java/info/bukova/isspst/ui/search/TripBillTransformer.java +++ b/src/main/java/info/bukova/isspst/ui/search/TripBillTransformer.java @@ -1,5 +1,6 @@ package info.bukova.isspst.ui.search; +import info.bukova.isspst.StringUtils; import info.bukova.isspst.data.TripBill; public class TripBillTransformer extends AbstractResultTransformer implements ResultTransformer { @@ -7,8 +8,10 @@ public class TripBillTransformer extends AbstractResultTransformer implements Re @Override protected void transform(Object object, SearchResult result) { TripBill tb = (TripBill)object; - result.setRecordName("Vyúčtování služební cesty: " + tb.getRequirement().getNumser()); - result.setDescription("Z " + tb.getRequirement().getFrom() + " do " + tb.getRequirement().getTo() + " - " + tb.getRequirement().getDescription()); + result.setRecordName(StringUtils.localize("TravelOrdersFormTitle") + ": " + tb.getRequirement().getNumser()); + result.setDescription(StringUtils.localize("TravelOrdersGridFrom") + " " + + tb.getRequirement().getFrom() + " " + StringUtils.localize("TravelOrdersGridTo") + " " + + tb.getRequirement().getTo() + " - " + tb.getRequirement().getDescription()); } } diff --git a/src/main/java/info/bukova/isspst/ui/search/TripRequirementTransformer.java b/src/main/java/info/bukova/isspst/ui/search/TripRequirementTransformer.java index 17dfa26a..feab9736 100644 --- a/src/main/java/info/bukova/isspst/ui/search/TripRequirementTransformer.java +++ b/src/main/java/info/bukova/isspst/ui/search/TripRequirementTransformer.java @@ -1,5 +1,6 @@ package info.bukova.isspst.ui.search; +import info.bukova.isspst.StringUtils; import info.bukova.isspst.data.TripRequirement; public class TripRequirementTransformer extends AbstractResultTransformer implements ResultTransformer { @@ -7,8 +8,10 @@ public class TripRequirementTransformer extends AbstractResultTransformer implem @Override protected void transform(Object object, SearchResult result) { TripRequirement tr = (TripRequirement)object; - result.setRecordName("Žádost o služební cestu: " + tr.getNumser()); - result.setDescription("Z " + tr.getFrom() + " do " + tr.getTo() + " - " + tr.getDescription()); + result.setRecordName(StringUtils.localize("TripRequirement") + ": " + tr.getNumser()); + result.setDescription(StringUtils.localize("TravelOrdersGridFrom") + " " + + tr.getFrom() + " " + StringUtils.localize("TravelOrdersGridTo") + " " + + tr.getTo() + " - " + tr.getDescription()); } } diff --git a/src/main/webapp/WEB-INF/locales/zk-label.properties b/src/main/webapp/WEB-INF/locales/zk-label.properties index e920cc65..a4952b0c 100644 --- a/src/main/webapp/WEB-INF/locales/zk-label.properties +++ b/src/main/webapp/WEB-INF/locales/zk-label.properties @@ -101,6 +101,7 @@ SuppliersGridColumnPhone=Telefon SuppliersGridColumnEmail=E-mail SuppliersGridColumnWWW=Web SuppliersGridColumnNote=Poznámka +Supplier=dodavatel AgendaUsers=Uživatelé UsersFormTitle=Uživatel @@ -220,6 +221,8 @@ TripBillTo=Tam TripBillBack=Zpět TripBillTotal=Celkem +TripRequirement=Požadavek na služební cestu + CentresForRequirements=Střediska, pro která lze vkládat požadavky WorkgroupMembership=Členství v komisích LogedInUser=Přihlášený uživatel: @@ -361,3 +364,6 @@ Help=Příručka GoogleDriveUrl=Odkaz na Google Drive ModuleNotActive=Modul není aktivovaný + +AgendaSearch=Vyhledávání +Search=Hledat diff --git a/src/main/webapp/WEB-INF/spring/root-context.xml b/src/main/webapp/WEB-INF/spring/root-context.xml index 3777c234..82215594 100644 --- a/src/main/webapp/WEB-INF/spring/root-context.xml +++ b/src/main/webapp/WEB-INF/spring/root-context.xml @@ -55,7 +55,7 @@ true update filesystem - /home/pepa/Dokumenty/dev/lucene + ./ org.apache.lucene.analysis.cz.CzechAnalyzer @@ -106,6 +106,7 @@ + diff --git a/src/main/webapp/app/mainMenu.zul b/src/main/webapp/app/mainMenu.zul index 415347fe..14f55811 100644 --- a/src/main/webapp/app/mainMenu.zul +++ b/src/main/webapp/app/mainMenu.zul @@ -135,5 +135,12 @@ href="/j_spring_security_logout" /> + + \ No newline at end of file diff --git a/src/main/webapp/search/index.zul b/src/main/webapp/app/search/index.zul similarity index 54% rename from src/main/webapp/search/index.zul rename to src/main/webapp/app/search/index.zul index 36bc8b13..57fa71b1 100644 --- a/src/main/webapp/search/index.zul +++ b/src/main/webapp/app/search/index.zul @@ -1,4 +1,4 @@ - + diff --git a/src/main/webapp/search/searchForm.zul b/src/main/webapp/app/search/searchForm.zul similarity index 59% rename from src/main/webapp/search/searchForm.zul rename to src/main/webapp/app/search/searchForm.zul index 297030da..fcfc66db 100644 --- a/src/main/webapp/search/searchForm.zul +++ b/src/main/webapp/app/search/searchForm.zul @@ -1,17 +1,25 @@ - + - + - - -