/*
* Copyright (C) 2012, Gerd Petermann
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 or
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
package uk.me.parabola.splitter;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import uk.me.parabola.splitter.tools.Long2IntClosedMapFunction;
import uk.me.parabola.splitter.tools.OSMId2ObjectMap;
import uk.me.parabola.splitter.tools.SparseLong2IntMap;
import uk.me.parabola.splitter.writer.OSMWriter;
/**
* Stores data that is needed in different passes of the program.
*
* @author GerdP
*
*/
public class DataStorer
{
public static final int NODE_TYPE =
0;
public static final int WAY_TYPE =
1;
public static final int REL_TYPE =
2;
private final int numOfAreas
;
private final Long2IntClosedMapFunction
[] maps =
new Long2IntClosedMapFunction
[3];
private final AreaDictionary areaDictionary
;
private final AreaIndex areaIndex
;
private SparseLong2IntMap usedWays =
null;
private final OSMId2ObjectMap
<Integer> usedRels =
new OSMId2ObjectMap
<>();
private boolean idsAreNotSorted
;
private OSMWriter
[] writers
;
/**
* map with relations that should be complete and are written to only one
* tile
*/
private final Long2ObjectOpenHashMap
<Integer> oneDistinctAreaOnlyRels =
new Long2ObjectOpenHashMap
<>();
private final OSMId2ObjectMap
<Integer> oneTileOnlyRels =
new OSMId2ObjectMap
<>();
/**
* Create a dictionary for a given number of writers
*
* @param overlapAmount
* @param numOfWriters
* the number of writers that are used
*/
DataStorer
(List<Area> areas,
int overlapAmount
) {
this.
numOfAreas = areas.
size();
this.
areaDictionary =
new AreaDictionary
(areas, overlapAmount
);
this.
areaIndex =
new AreaGrid
(areaDictionary
);
return;
}
public int getNumOfAreas
() {
return numOfAreas
;
}
public AreaDictionary getAreaDictionary
() {
return areaDictionary
;
}
public Area getArea
(int idx
) {
return areaDictionary.
getArea(idx
);
}
public Area getExtendedArea
(int idx
) {
return areaDictionary.
getExtendedArea(idx
);
}
public void setWriters
(OSMWriter
[] writers
) {
this.
writers = writers
;
}
public void setWriterMap
(int type, Long2IntClosedMapFunction nodeWriterMap
) {
maps
[type
] = nodeWriterMap
;
}
public Long2IntClosedMapFunction getWriterMap
(int type
) {
return maps
[type
];
}
public AreaIndex getGrid
() {
return areaIndex
;
}
public SparseLong2IntMap getUsedWays
() {
return usedWays
;
}
public OSMId2ObjectMap
<Integer> getUsedRels
() {
return usedRels
;
}
public void setUsedWays
(SparseLong2IntMap ways
) {
usedWays = ways
;
}
public boolean isIdsAreNotSorted
() {
return idsAreNotSorted
;
}
public void setIdsAreNotSorted
(boolean idsAreNotSorted
) {
this.
idsAreNotSorted = idsAreNotSorted
;
}
public void restartWriterMaps
() {
for (Long2IntClosedMapFunction map : maps
) {
if (map
!=
null) {
try {
map.
close();
} catch (IOException e
) {
// TODO Auto-generated catch block
e.
printStackTrace();
}
}
}
}
public void switchToSeqAccess
(File fileOutputDir
) throws IOException {
boolean msgWritten =
false;
long start =
System.
currentTimeMillis();
for (Long2IntClosedMapFunction map : maps
) {
if (map
!=
null) {
if (!msgWritten
) {
System.
out.
println("Writing results of MultiTileAnalyser to temp files ...");
msgWritten =
true;
}
map.
switchToSeqAccess(fileOutputDir
);
}
}
System.
out.
println("Writing temp files took " +
(System.
currentTimeMillis() - start
) +
" ms");
}
public void finish
() {
for (Long2IntClosedMapFunction map : maps
) {
if (map
!=
null)
map.
finish();
}
}
public void stats
(final String prefix
) {
for (Long2IntClosedMapFunction map : maps
) {
if (map
!=
null)
map.
stats(prefix
);
}
}
public OSMWriter
[] getWriters
() {
return writers
;
}
public void storeRelationAreas
(long id, AreaSet areaSet
) {
oneDistinctAreaOnlyRels.
put(id, areaDictionary.
translate(areaSet
));
}
public Integer getOneTileOnlyRels
(long id
) {
return oneTileOnlyRels.
get(id
);
}
/**
* If the ids in oneTileOnlyRels were produced with a different set
* of areas we have to translate the values
*
* @param distinctAreas
* list of distinct (non-overlapping) areas
* @param distinctDataStorer
*/
public void translateDistinctToRealAreas
(DataStorer distinctDataStorer
) {
List<Area> distinctAreas = distinctDataStorer.
getAreaDictionary().
getAreas();
Map<Area,
Integer> map =
new HashMap<>();
for (Area distinctArea : distinctAreas
) {
if (!distinctArea.
isPseudoArea()) {
AreaSet w =
new AreaSet
();
for (int i =
0; i
< getNumOfAreas
(); i++
) {
if (this.
areaDictionary.
getArea(i
).
contains(distinctArea
)) {
w.
set(i
);
}
}
map.
put(distinctArea,
this.
areaDictionary.
translate(w
));
}
}
for (Entry
<Long,
Integer> e : distinctDataStorer.
oneDistinctAreaOnlyRels.
entrySet()) {
AreaSet singleArea = distinctDataStorer.
getAreaDictionary().
getSet(e.
getValue());
assert singleArea.
cardinality() ==
1;
int pos = singleArea.
iterator().
next();
if (!distinctAreas.
get(pos
).
isPseudoArea()) {
Integer areaIdx = map.
get(distinctAreas.
get(pos
));
if (areaIdx ==
null)
throw new SplitFailedException
("failed to find index for area " + distinctAreas.
get(pos
));
oneTileOnlyRels.
put(e.
getKey(), areaIdx
);
} else {
oneTileOnlyRels.
put(e.
getKey(), AbstractMapProcessor.
UNASSIGNED);
}
}
}
}