Browse Source

Merge branch 'feature/searchElement' into develop

develop
LO Kam Tao Leo 3 years ago
parent
commit
e3744724c3
  1. 64
      src/main/java/org/leolo/map/osm/extract/ExtractElement.java
  2. 12
      src/main/java/org/leolo/map/osm/extract/SearchProvider.java
  3. 112
      src/main/java/org/leolo/map/osm/extract/SearchProviderManager.java
  4. 24
      src/main/java/org/leolo/map/osm/extract/format/SimpleStringSearchProvider.java
  5. 56
      src/main/java/org/leolo/map/osm/extract/model/ActionFile.java
  6. 67
      src/main/java/org/leolo/map/osm/extract/model/SearchItem.java

64
src/main/java/org/leolo/map/osm/extract/ExtractElement.java

@ -1,9 +1,6 @@
package org.leolo.map.osm.extract;
import de.topobyte.osm4j.core.access.DefaultOsmHandler;
import de.topobyte.osm4j.core.access.OsmInputException;
import de.topobyte.osm4j.core.access.OsmIterator;
import de.topobyte.osm4j.core.access.OsmReader;
import de.topobyte.osm4j.core.access.*;
import de.topobyte.osm4j.core.model.iface.*;
import de.topobyte.osm4j.pbf.seq.PbfReader;
import org.apache.commons.cli.*;
@ -168,6 +165,7 @@ public class ExtractElement {
System.exit(3);
return;
}
doSearch(dbFile, af);
for(ExtractItem ei:af.getRelation()){
pendingRelations.add(ei.getId());
}
@ -177,7 +175,6 @@ public class ExtractElement {
for(ExtractItem ei:af.getNode()){
pendingNodes.add(ei.getId());
}
doSearch(dbFile, af);
expandRelations(dbFile, 1);
processWay(dbFile);
processNode(dbFile);
@ -190,7 +187,62 @@ public class ExtractElement {
* @param af The file which defines the action to be performed
*/
private void doSearch(InputFile dbFile, ActionFile af) throws IOException{
//Placeholder
if(af.getSearches().isEmpty()){
return;
}
OsmReader reader = new PbfReader(dbFile.getInputStream(), true);
reader.setHandler(new OsmHandler() {
@Override
public void handle(OsmBounds osmBounds) throws IOException {
}
@Override
public void handle(OsmNode osmNode) throws IOException {
for(SearchItem si:af.getSearches()){
if(si.matchNode(osmNode)){
log.atInfo().log("Matched Node {}", osmNode.getId());
ExtractItem ei = new ExtractItem();
ei.setId(osmNode.getId());
af.addNode(ei);
}
}
}
@Override
public void handle(OsmWay osmWay) throws IOException {
for(SearchItem si:af.getSearches()){
if(si.matchWay(osmWay)){
log.atInfo().log("Matched Way {}", osmWay.getId());
ExtractItem ei = new ExtractItem();
ei.setId(osmWay.getId());
af.addWay(ei);
}
}
}
@Override
public void handle(OsmRelation osmRelation) throws IOException {
for(SearchItem si:af.getSearches()){
if(si.matchRelation(osmRelation)){
log.atInfo().log("Matched Relation {}", osmRelation.getId());
ExtractItem ei = new ExtractItem();
ei.setId(osmRelation.getId());
af.addRelation(ei);
}
}
}
@Override
public void complete() throws IOException {
log.atInfo().log("Finish reading the DB file");
}
});
try {
reader.read();
} catch (OsmInputException e) {
log.atError().withThrowable(e).log("Error when reading the input!");
}
}
private void processNode(InputFile dbFile) throws IOException{

12
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();
}

112
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<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();
}
}

24
src/main/java/org/leolo/map/osm/extract/format/SimpleStringSearchProvider.java

@ -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+"]";
}
}

56
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 {
@ -24,6 +27,11 @@ public class ActionFile {
private Map<Long,ExtractItem> way = new Hashtable<>();
private Map<Long,ExtractItem> node = new Hashtable<>();
private String baseLanguage;
private HashSet<String> otherLanguage = new HashSet<>();
private Vector<SearchItem> searches = new Vector<>();
public ActionFile(InputFile path) throws IOException, SAXException, ParserConfigurationException {
log.atInfo().log("Parsing action file");
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
@ -86,6 +94,42 @@ public class ActionFile {
continue;
}
}
NodeList languages = rootElement.getElementsByTagName("language");
if(languages.getLength()>0){
NodeList children = languages.item(0).getChildNodes();
for(int i=0;i<children.getLength();i++) {
Node child = children.item(i);
if("base".equals(child.getNodeName())){
this.baseLanguage = child.getTextContent();
}else if("other".equals(child.getNodeName())){
this.otherLanguage.add(child.getTextContent());
}
}
}
NodeList searchesNodeList = rootElement.getElementsByTagName("searches");
if(searchesNodeList.getLength()>0){
NodeList searches = searchesNodeList.item(0).getChildNodes();
for(int i=0;i<searches.getLength();i++){
Node child = searches.item(i);
if(child==null||"#text".equals(child.getNodeName()) || "#comment".equals(child.getNodeName())){
continue;
}
log.atDebug().log("Search type {}; search key: {}", child.getNodeName(), child.getTextContent());
Class clazz = SearchProviderManager.getInstance().get(child.getNodeName());
if(clazz==null){
log.atError().log("Unknown search type {}", child.getNodeName());
}else{
try {
SearchItem si = (SearchItem) clazz.getConstructor().newInstance();
si.setSearchKey(child.getTextContent());
si.setActionFile(this);
this.searches.add(si);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
}
@ -119,4 +163,16 @@ public class ActionFile {
if(!way.containsKey(ei.getId()))
way.put(ei.getId(), ei);
}
public String getBaseLanguage() {
return baseLanguage;
}
public HashSet<String> getOtherLanguage() {
return otherLanguage;
}
public Vector<SearchItem> getSearches() {
return searches;
}
}

67
src/main/java/org/leolo/map/osm/extract/model/SearchItem.java

@ -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…
Cancel
Save