/*
* This file is part of gwap, an open platform for games with a purpose
*
* Copyright (C) 2013
* Project play4science
* Lehr- und Forschungseinheit für Programmier- und Modellierungssprachen
* Ludwig-Maximilians-Universität München
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gwap.mit.admin;
import gwap.model.resource.Location;
import gwap.model.resource.LocationHierarchy;
import gwap.model.resource.LocationHierarchy.LocationHierarchyType;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityManager;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.security.Restrict;
import org.jboss.seam.log.Log;
/**
* @author Fabian Kneißl
*/
@Name("mitAdminLocationHierarchyCreator")
@Restrict("#{s:hasRole('admin')}")
public class LocationHierarchyCreator implements Serializable {
@In
private EntityManager entityManager;
@Logger
private Log log;
private Map<LocationHierarchyType,Integer> insertedLHs;
private Map<Long,Float> insertedLocationPairs;
private static final String hierarchyName = "mit.scoring";
private Long MAX_LOCATION_ID;
@SuppressWarnings("unchecked")
public void recreateHierarchy() {
int deleteResult = entityManager.createQuery("delete from LocationHierarchy where name = :name")
.setParameter("name", hierarchyName)
.executeUpdate();
entityManager.flush();
log.info("Deleted #0 rows from LocationHierarchy", deleteResult);
MAX_LOCATION_ID = ((Number) entityManager.createQuery("select max(id) from Location").getSingleResult()).longValue();
insertedLHs = new HashMap<LocationHierarchyType, Integer>();
insertedLocationPairs = new HashMap<Long, Float>();
// Insert self and neighbors
List<Location> allLocations = entityManager.createNamedQuery("location.allButUserDefined").getResultList();
for (Location l : allLocations) {
createLH(l, l, LocationHierarchyType.SELF);
for (Location n : l.getNeighbors()) {
createLH(l, n, LocationHierarchyType.NEIGHBOR);
}
}
log.info("Inserted #0 locations and #1 neighbors", insertedLHs.get(LocationHierarchyType.SELF), insertedLHs.get(LocationHierarchyType.NEIGHBOR));
entityManager.flush();
insertFromHierarchy("locationHierarchy.allMIT1stOrder");
insertFromHierarchy("locationHierarchy.allMIT2ndOrder");
insertFromHierarchy("locationHierarchy.allMIT3rdOrder");
insertFromHierarchy("locationHierarchy.allMIT4thOrder");
log.info("Inserted #0 descendants and #0 ancestors", insertedLHs.get(LocationHierarchyType.DESCENDANT), insertedLHs.get(LocationHierarchyType.ANCESTOR));
entityManager.flush();
// Insert hierarchical neighbors
List<Object[]> flattenedNeighbors = entityManager.createQuery(
"select l1, l2 from Location l1 join l1.neighbors n join n.hierarchies lh join lh.sublocation l2 " +
"where lh.name=:name and lh.type =:type")
.setParameter("name", hierarchyName)
.setParameter("type", LocationHierarchyType.DESCENDANT)
.getResultList();
for (Object[] locations : flattenedNeighbors) {
Location l1 = (Location) locations[0];
Location l2 = (Location) locations[1];
createLH(l1, l2, LocationHierarchyType.NEIGHBOR_DESCENDANT);
createLH(l2, l1, LocationHierarchyType.NEIGHBOR_ANCESTOR);
}
log.info("Inserted #0 descendant-neighbors and #0 ancestor-neighbors", insertedLHs.get(LocationHierarchyType.NEIGHBOR_DESCENDANT), insertedLHs.get(LocationHierarchyType.NEIGHBOR_ANCESTOR));
entityManager.flush();
log.info("Finished");
}
private void insertFromHierarchy(String query) {
List<Object[]> locationsList = entityManager.createNamedQuery(query).getResultList();
for (Object[] locations : locationsList) {
Location l1 = (Location) locations[0];
Location l2 = (Location) locations[1];
createLH(l1, l2, LocationHierarchyType.DESCENDANT);
createLH(l2, l1, LocationHierarchyType.ANCESTOR);
}
}
private void createLH(Location location, Location sublocation, LocationHierarchyType type) {
Float higherValue = insertedLocationPairs.get(location.getId() + sublocation.getId()*(MAX_LOCATION_ID+1));
if (higherValue != null) {
if (higherValue.floatValue() >= type.getCorrelation())
return;
else {
// Delete old LocationHierarchy
Object old = entityManager.createNamedQuery("locationHierarchy.byLocationsAndName")
.setParameter("name", hierarchyName)
.setParameter("location", location)
.setParameter("sublocation", sublocation)
.getSingleResult();
entityManager.remove(old);
}
}
insertedLocationPairs.put(location.getId() + sublocation.getId()*(MAX_LOCATION_ID+1), type.getCorrelation());
LocationHierarchy create = new LocationHierarchy();
create.setLocation(location);
create.setSublocation(sublocation);
create.setName(hierarchyName);
create.setType(type);
create.setCorrelation(type.getCorrelation());
entityManager.persist(create);
insertedLHs.put(type, (insertedLHs.get(type) == null ? 0 : insertedLHs.get(type)) + 1);
}
}