From cea17139d2a46d329715725a7316b851461bd43a Mon Sep 17 00:00:00 2001 From: LO Kam Tao Leo Date: Fri, 23 Sep 2022 21:22:21 +0100 Subject: [PATCH] Skeleton to provide search function --- .../org/leolo/map/osm/extract/SearchProvider.java | 12 +++ .../map/osm/extract/SearchProviderManager.java | 112 +++++++++++++++++++++ .../leolo/map/osm/extract/model/ActionFile.java | 27 +++++ .../leolo/map/osm/extract/model/SearchItem.java | 1 + 4 files changed, 152 insertions(+) create mode 100644 src/main/java/org/leolo/map/osm/extract/SearchProvider.java create mode 100644 src/main/java/org/leolo/map/osm/extract/SearchProviderManager.java diff --git a/src/main/java/org/leolo/map/osm/extract/SearchProvider.java b/src/main/java/org/leolo/map/osm/extract/SearchProvider.java new file mode 100644 index 0000000..acbe27b --- /dev/null +++ b/src/main/java/org/leolo/map/osm/extract/SearchProvider.java @@ -0,0 +1,12 @@ +package org.leolo.map.osm.extract; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface SearchProvider { + String[] searchKey(); +} diff --git a/src/main/java/org/leolo/map/osm/extract/SearchProviderManager.java b/src/main/java/org/leolo/map/osm/extract/SearchProviderManager.java new file mode 100644 index 0000000..c4820c8 --- /dev/null +++ b/src/main/java/org/leolo/map/osm/extract/SearchProviderManager.java @@ -0,0 +1,112 @@ +package org.leolo.map.osm.extract; + +import eu.infomas.annotation.AnnotationDetector; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.leolo.map.osm.extract.model.SearchItem; + +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.util.*; +import java.util.function.BiConsumer; + +public class SearchProviderManager { + + private static SearchProviderManager instance; + private Logger log = LogManager.getLogger(); + private Hashtable items = new Hashtable<>(); + + public static synchronized SearchProviderManager getInstance(){ + if(instance==null){ + instance = new SearchProviderManager(); + } + return instance; + } + + private SearchProviderManager(){ + AnnotationDetector.TypeReporter reporter = new AnnotationDetector.TypeReporter() { + @Override + public void reportTypeAnnotation(Class annoClass, String clazz) { + log.atDebug().log("Class {} has annotation {}", clazz, annoClass.getName()); + try { + Class typeClass = Class.forName(clazz); + if(SearchItem.class.isAssignableFrom(typeClass)){ + log.atDebug().log("Class {} is an output formatter", clazz); + SearchProvider of = (SearchProvider) typeClass.getAnnotation(SearchProvider.class); + for(String format: of.searchKey()){ + if(items.containsKey(format)){ + log.atWarn().log("Duplicated search type {}. Shared by (at least) {} and {}", + format, + typeClass.getName(), + items.get(format).getName() + ); + }else{ + items.put(format, typeClass); + log.atInfo().log("Registering class {} for search type {}", typeClass, format); + } + } + }else{ + log.atError().log("Class {} does not implements OutputFormat but have annotation @OutputFormatter", clazz); + } + } catch (ClassNotFoundException e) { + log.atError().withThrowable(e).log(e.getMessage()); + } + } + + @Override + public Class[] annotations() { + return new Class[]{SearchProvider.class}; + } + }; + final AnnotationDetector cf = new AnnotationDetector(reporter); + try { + cf.detect(); + } catch (IOException e) { + log.atError().withThrowable(e).log(e.getMessage()); + } + } + + public int size() { + return items.size(); + } + + public boolean isEmpty() { + return items.isEmpty(); + } + + public Enumeration keys() { + return items.keys(); + } + + public boolean containsKey(Object key) { + return items.containsKey(key); + } + + public Class get(Object key) { + return items.get(key); + } + + public Set keySet() { + return items.keySet(); + } + + public void forEach(BiConsumer action) { + items.forEach(action); + } + + public int getOutputFormatterCount(){ + HashSet set = new HashSet<>(); + for(Class clazz:items.values()){ + set.add(clazz); + } + return set.size(); + } + + public int getSearchProviderCount(){ + HashSet set = new HashSet<>(); + for(Class clazz:items.values()){ + set.add(clazz); + } + return set.size(); + } +} diff --git a/src/main/java/org/leolo/map/osm/extract/model/ActionFile.java b/src/main/java/org/leolo/map/osm/extract/model/ActionFile.java index bf5c3ac..831b588 100644 --- a/src/main/java/org/leolo/map/osm/extract/model/ActionFile.java +++ b/src/main/java/org/leolo/map/osm/extract/model/ActionFile.java @@ -2,6 +2,7 @@ package org.leolo.map.osm.extract.model; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.leolo.map.osm.extract.SearchProviderManager; import org.leolo.map.osm.extract.util.InputFile; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -9,11 +10,13 @@ import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; +import javax.management.ReflectionException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import java.io.File; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; import java.util.*; public class ActionFile { @@ -27,6 +30,7 @@ public class ActionFile { private String baseLanguage; private HashSet otherLanguage = new HashSet<>(); + private Vector searches = new Vector<>(); public ActionFile(InputFile path) throws IOException, SAXException, ParserConfigurationException { log.atInfo().log("Parsing action file"); @@ -102,6 +106,29 @@ public class ActionFile { } } } + NodeList searchesNodeList = rootElement.getElementsByTagName("searches"); + if(searchesNodeList.getLength()>0){ + NodeList searches = searchesNodeList.item(0).getChildNodes(); + for(int i=0;i