6 changed files with 329 additions and 6 deletions
@ -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(); |
||||||
|
} |
||||||
@ -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<String, Class> 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<? extends Annotation> 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<? extends Annotation>[] 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<String> keys() { |
||||||
|
return items.keys(); |
||||||
|
} |
||||||
|
|
||||||
|
public boolean containsKey(Object key) { |
||||||
|
return items.containsKey(key); |
||||||
|
} |
||||||
|
|
||||||
|
public Class get(Object key) { |
||||||
|
return items.get(key); |
||||||
|
} |
||||||
|
|
||||||
|
public Set<String> keySet() { |
||||||
|
return items.keySet(); |
||||||
|
} |
||||||
|
|
||||||
|
public void forEach(BiConsumer<? super String, ? super Class> action) { |
||||||
|
items.forEach(action); |
||||||
|
} |
||||||
|
|
||||||
|
public int getOutputFormatterCount(){ |
||||||
|
HashSet<Class> set = new HashSet<>(); |
||||||
|
for(Class clazz:items.values()){ |
||||||
|
set.add(clazz); |
||||||
|
} |
||||||
|
return set.size(); |
||||||
|
} |
||||||
|
|
||||||
|
public int getSearchProviderCount(){ |
||||||
|
HashSet<Class> set = new HashSet<>(); |
||||||
|
for(Class clazz:items.values()){ |
||||||
|
set.add(clazz); |
||||||
|
} |
||||||
|
return set.size(); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,24 @@ |
|||||||
|
package org.leolo.map.osm.extract.format; |
||||||
|
|
||||||
|
import org.leolo.map.osm.extract.SearchProvider; |
||||||
|
import org.leolo.map.osm.extract.model.SearchItem; |
||||||
|
|
||||||
|
@SearchProvider(searchKey = "name") |
||||||
|
public class SimpleStringSearchProvider extends SearchItem { |
||||||
|
|
||||||
|
private String searchKey; |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean matchString(String target) { |
||||||
|
return searchKey.equalsIgnoreCase(target.strip()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setSearchKey(String searchKey) { |
||||||
|
this.searchKey = searchKey.strip(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public String toString(){ |
||||||
|
return "SimpleString["+searchKey+"]"; |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,67 @@ |
|||||||
|
package org.leolo.map.osm.extract.model; |
||||||
|
|
||||||
|
import de.topobyte.osm4j.core.model.iface.OsmEntity; |
||||||
|
import de.topobyte.osm4j.core.model.iface.OsmNode; |
||||||
|
import de.topobyte.osm4j.core.model.iface.OsmRelation; |
||||||
|
import de.topobyte.osm4j.core.model.iface.OsmWay; |
||||||
|
|
||||||
|
import java.util.HashSet; |
||||||
|
import java.util.Set; |
||||||
|
|
||||||
|
public abstract class SearchItem { |
||||||
|
|
||||||
|
private ActionFile af; |
||||||
|
|
||||||
|
private HashSet<String> tagName = new HashSet<>(); |
||||||
|
|
||||||
|
public SearchItem(ActionFile af){ |
||||||
|
this.af = af; |
||||||
|
setTags(); |
||||||
|
} |
||||||
|
|
||||||
|
public SearchItem(){ |
||||||
|
//Empty constructor
|
||||||
|
} |
||||||
|
|
||||||
|
protected final void setActionFile(ActionFile af){ |
||||||
|
this.af = af; |
||||||
|
setTags(); |
||||||
|
} |
||||||
|
|
||||||
|
private void setTags(){ |
||||||
|
tagName.add("name:"+af.getBaseLanguage()); |
||||||
|
for(String lang:af.getOtherLanguage()){ |
||||||
|
tagName.add("name:"+lang); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public abstract boolean matchString(String target); |
||||||
|
public abstract void setSearchKey(String searchKey); |
||||||
|
|
||||||
|
private boolean matchEntity(OsmEntity entity){ |
||||||
|
for(int i=0;i<entity.getNumberOfTags();i++){ |
||||||
|
if("name".equalsIgnoreCase(entity.getTag(i).getKey()) && matchString(entity.getTag(i).getValue())){ |
||||||
|
return true; |
||||||
|
} |
||||||
|
if(af != null){ |
||||||
|
for(String tag:tagName){ |
||||||
|
if(tag.equalsIgnoreCase(entity.getTag(i).getKey()) && matchString(entity.getTag(i).getValue())){ |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
public boolean matchNode(OsmNode node){ |
||||||
|
return matchEntity(node); |
||||||
|
} |
||||||
|
|
||||||
|
public boolean matchWay(OsmWay way){ |
||||||
|
return matchEntity(way); |
||||||
|
} |
||||||
|
|
||||||
|
public boolean matchRelation(OsmRelation relation){ |
||||||
|
return matchEntity(relation); |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue