Java tutorial
/* * Copyright (c) 2009 - 2010. School of Information Technology and Electrical * Engineering, The University of Queensland. This software is being developed * for the "Phenomics Ontoogy Driven Data Management Project (PODD)" project. * PODD is a National e-Research Architecture Taskforce (NeAT) project * co-funded by ANDS and ARCS. * * PODD is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * PODD 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. * * You should have received a copy of the GNU General Public License * along with PODD. If not, see <http://www.gnu.org/licenses/>. */ package podd.util; import info.aduna.collections.iterators.CloseableIterator; import org.apache.log4j.Logger; import org.apache.tika.io.IOUtils; import org.hibernate.SessionFactory; import org.openrdf.repository.RepositoryConnection; import org.openrdf.rio.RDFFormat; import org.semanticweb.owlapi.apibinding.OWLManager; import org.semanticweb.owlapi.io.OWLOntologyDocumentTarget; import org.semanticweb.owlapi.io.RDFXMLOntologyFormat; import org.semanticweb.owlapi.io.StringDocumentTarget; import org.semanticweb.owlapi.model.OWLAxiom; import org.semanticweb.owlapi.model.OWLClass; import org.semanticweb.owlapi.model.OWLClassAxiom; import org.semanticweb.owlapi.model.OWLClassExpression; import org.semanticweb.owlapi.model.OWLEntity; import org.semanticweb.owlapi.model.OWLOntology; import org.semanticweb.owlapi.model.OWLOntologyChangeException; import org.semanticweb.owlapi.model.OWLOntologyIRIMapper; import org.semanticweb.owlapi.model.OWLOntologyManager; //import org.semanticweb.owlapi.model.OWLOntologyURIMapper; import org.semanticweb.owlapi.model.OWLSubClassOfAxiom; import org.springframework.core.io.AbstractResource; import org.springframework.core.io.Resource; import podd.client.PoddClientException; import podd.client.owl.PoddClientOntologyRegistry; import podd.dataaccess.AdministrationSettingsDAO; import podd.dataaccess.DatastoreRegistryDAO; import podd.dataaccess.PoddConceptDAO; import podd.dataaccess.RepositoryRoleDAO; import podd.dataaccess.UserDAO; import podd.dataaccess.exception.DataAccessException; import podd.dataaccess.hibernate.HibernateSessionHelper; import podd.model.EntityFactory; import podd.model.datastore.Datastore; import podd.model.entity.PoddConcept; import podd.model.user.AdministrationSettings; import podd.model.user.RepositoryRole; import podd.model.user.User; import podd.model.user.RepositoryRole; import podd.owl.OntologyHelper; import podd.owl.OntologyRegistry; import podd.triples.SesameRepoWrapper; import podd.util.common.vocabulary.EnumerableRDFNamespace; import uk.ac.manchester.cs.owl.owlapi.OWLOntologyIRIMapperImpl; //import uk.ac.manchester.cs.owl.OWLOntologyURIMapperImpl; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Method; import org.semanticweb.owlapi.model.IRI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import static org.semanticweb.owlapi.model.AxiomType.SUBCLASS_OF; import static podd.model.user.AdministrationSettings.SELF_REGISTRATION_ENABLED; import static podd.model.user.AdministrationSettings.USER_STATUS_ACTIVE; import static podd.model.user.UserStatus.ACTIVE; import static podd.util.common.Constants.PODD_URI; import static podd.util.common.vocabulary.PoddModelNamespace.PODD_MODEL; import static podd.util.common.vocabulary.PoddNamespaceHelper.PODD_NAMESPACE_HELPER; /** * @author Yuan-Fang Li * @version $Id$ */ public class WebappInitialisationUtil { private static final int TWENTY_MILLISECONDS = 20; private static final String USERNAME_KEY = "userName"; private final Logger logger = Logger.getLogger(getClass()); private User adminUser; private Resource repoAdminUserResource; private Resource datastoreResource; private AbstractResource ontologyDirectory; private String ontologyNames; private boolean toReset; private boolean toIngest; private UserDAO userDao; private DatastoreRegistryDAO datastoreRegistryDao; private RepositoryRoleDAO rrDao; private AdministrationSettingsDAO adminSettingsDao; private PoddConceptDAO conceptDao; private OntologyHelper ontologyHelper; private EntityFactory entityFactory; private SesameRepoWrapper repoWrapper; private OntologyRegistry ontologyRegistry; private List<File> ontologyFiles; private SessionFactory sessionFactory; public void setToReset(boolean toRest) { this.toReset = toRest; } public void setOntologyDirectory(AbstractResource ontologyDirectory) { this.ontologyDirectory = ontologyDirectory; } public void setOntologyNames(String ontologies) { this.ontologyNames = ontologies; } public void setRepoAdminUserResource(Resource repoAdminUserResource) { this.repoAdminUserResource = repoAdminUserResource; } public void setDatastoreResource(Resource datastoreResource) { this.datastoreResource = datastoreResource; } public void setUserDao(UserDAO userDao) { this.userDao = userDao; } public void setDatastoreRegistryDao(DatastoreRegistryDAO datastoreRegistryDao) { this.datastoreRegistryDao = datastoreRegistryDao; } public void setConceptDao(PoddConceptDAO conceptDao) { this.conceptDao = conceptDao; } public void setRrDao(RepositoryRoleDAO rrDao) { this.rrDao = rrDao; } public void setAdminSettingsDao(AdministrationSettingsDAO adminSettingsDao) { this.adminSettingsDao = adminSettingsDao; } public void setOntologyHelper(OntologyHelper ontologyHelper) { this.ontologyHelper = ontologyHelper; } public void setEntityFactory(EntityFactory entityFactory) { this.entityFactory = entityFactory; } public void setOntologyRegistry(OntologyRegistry ontologyRegistry) { this.ontologyRegistry = ontologyRegistry; } public void setToIngest(boolean toIngest) { this.toIngest = toIngest; } public void setRepoWrapper(SesameRepoWrapper repoWrapper) { this.repoWrapper = repoWrapper; } public SessionFactory getSessionFactory() { return sessionFactory; } public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } public void doInitialize() throws Exception { HibernateSessionHelper.openSession(sessionFactory); try { if (toReset) { logger.info("Initializing PODD repository."); setupDefaultRepoRoles(); setupDefaultAdministrationSettings(); adminUser = createRepoAdminUser(repoAdminUserResource); createDefaultDatastore(datastoreResource); processAndAddOWLClasses(); initializePoddClientOntologyRegistry(); addOntologiesToTripleStore(); } } finally { HibernateSessionHelper.closeSession(sessionFactory); } } private void addOntologiesToTripleStore() throws Exception { RDFXMLOntologyFormat format = new RDFXMLOntologyFormat(); final RepositoryConnection conn = repoWrapper.getConnection(); try { for (OWLOntology ont : ontologyRegistry.getOntologies()) { OWLOntologyDocumentTarget target = new StringDocumentTarget(); ont.getOWLOntologyManager().saveOntology(ont, format, target); final InputStream in = IOUtils.toInputStream(target.toString()); try { conn.add(in, ont.getOntologyID().getOntologyIRI().toString(), RDFFormat.RDFXML); logger.info( "Added ontology to triple store: " + ont.getOntologyID().getOntologyIRI().toString()); } finally { IOUtils.closeQuietly(in); } } conn.commit(); } finally { conn.close(); } } private void processAndAddOWLClasses() throws DataAccessException { ontologyFiles = new LinkedList<File>(); for (String filename : ontologyNames.split(",")) { try { File file = new File(ontologyDirectory.getFile().getAbsolutePath() + File.separator + filename); ontologyFiles.add(file); } catch (IOException e) { throw new DataAccessException("Error loading ontology from directory: " + ontologyDirectory.getFilename() + " : " + filename, e); } } ingestPoddConceptsFromOntologies(); } /** * Initialize the PODD Client ontology registry * @throws PoddClientException */ private void initializePoddClientOntologyRegistry() throws PoddClientException { List<IRI> ontologyURIs = new ArrayList<IRI>(); for (File file : ontologyFiles) { ontologyURIs.add(IRI.create(file.toURI())); } PoddClientOntologyRegistry.getInstance().setModels(ontologyURIs); } public User getRepoAdmin() { return adminUser; } private User createRepoAdminUser(Resource resource) { try { File propertyFile = resource.getFile(); final FileReader fileReader = new FileReader(propertyFile); Properties properties = new Properties(); properties.load(fileReader); // try to load the user and if it doesn't exist create a new one String username = properties.get(USERNAME_KEY).toString(); User admin = userDao.loadByUserName(username); if (null == admin) { admin = entityFactory.createUser(null); } // add properties to the user for (Object key : properties.keySet()) { final String value = properties.get(key).toString(); String methodName = getSetterMethodName((String) key); final Method method = User.class.getDeclaredMethod(methodName, String.class); method.invoke(admin, value); } admin.setStatus(ACTIVE); admin.setRepositoryRole(rrDao.getRepositoryRole(RepositoryRole.REPOSITORY_ADMINISTRATOR.getName())); logger.info("Creating repository administrator user: " + admin.getUserName()); userDao.saveOrUpdate(admin); return admin; } catch (Exception e) { throw new RuntimeException(e); } } private void createDefaultDatastore(Resource resource) { if (null == resource) return; try { File propertyFile = resource.getFile(); final FileReader fileReader = new FileReader(propertyFile); Properties properties = new Properties(); properties.load(fileReader); // try to load the datastore and if it doesn't exist create a new one String ip = properties.get("ip").toString(); int port = Integer.parseInt(properties.get("port").toString()); String login = properties.get("login").toString(); String defaultDirectory = properties.get("defaultDirectory").toString(); Datastore datastore = datastoreRegistryDao.loadByIP(ip); if (null == datastore) { datastore = new Datastore(ip, port, login, defaultDirectory); } else { datastore.setPort(port); datastore.setLoginId(login); datastore.setDefaultDirectory(defaultDirectory); } datastore.setAccessMethod(properties.get("accessMethod").toString()); logger.info("Creating default datastore: " + datastore.getLoginId() + "@" + datastore.getIp() + ":" + datastore.getPort()); datastoreRegistryDao.saveOrUpdate(datastore); } catch (Exception e) { throw new RuntimeException(e); } } private String getSetterMethodName(String fieldName) { String methodName = "set"; String capitalFieldName = fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1); return methodName + capitalFieldName; } private void ingestPoddConceptsFromOntologies() { Map<OWLClass, Set<OWLAxiom>> conceptClasses = new HashMap<OWLClass, Set<OWLAxiom>>(); try { PODD_NAMESPACE_HELPER.addNamespace(PODD_MODEL.uri, PODD_MODEL); OWLOntologyManager manager = OWLManager.createOWLOntologyManager(); final OWLClass poddClass = manager.getOWLDataFactory() .getOWLClass(IRI.create(PODD_MODEL.PODD_CONCEPT.getURI())); final OWLOntologyIRIMapperImpl mapper = new OWLOntologyIRIMapperImpl(); manager.addIRIMapper(mapper); for (File file : ontologyFiles) { processOneOntology(file, conceptClasses, poddClass, mapper, manager); } if (toIngest) { logger.info("Ingesting a total of " + conceptClasses.size() + " concepts."); int i = 0; for (OWLClass cls : conceptClasses.keySet()) { createPoddConcept(cls, manager, conceptClasses.get(cls), ++i); } } } catch (Exception e) { logger.error("Error ingesting concepts", e); throw new RuntimeException(e); } } private void processOneOntology(File file, Map<OWLClass, Set<OWLAxiom>> map, OWLClass poddClass, OWLOntologyIRIMapperImpl mapper, OWLOntologyManager manager) throws Exception { // OWLOntologyManager manager = ontologyRegistry.getOntologyManager(); logger.debug("Loading ontology file: " + file.toURI().toString()); final OWLOntology ontology = manager.loadOntologyFromOntologyDocument(file); mapper.addMapping(ontology.getOntologyID().getOntologyIRI(), IRI.create(file.toURI())); ontologyRegistry.addModel(ontology); enrichNamespace(ontology); final Set<OWLSubClassOfAxiom> owlSubClassAxiomSet = ontology.getAxioms(SUBCLASS_OF); for (OWLSubClassOfAxiom axiom : owlSubClassAxiomSet) { final OWLClassExpression owlClass = axiom.getSubClass(); if (!owlClass.isAnonymous() && ontologyRegistry.isSubClassOf(owlClass.asOWLClass(), poddClass, ontology)) { addToMap(owlClass.asOWLClass(), ontology, map); } } } private void enrichNamespace(OWLOntology ontology) throws URISyntaxException { String namespace = ontology.getOntologyID().getOntologyIRI().toString(); if (!namespace.endsWith("#")) { namespace = namespace + "#"; } if (null == PODD_NAMESPACE_HELPER.getNamespace(namespace)) { PODD_NAMESPACE_HELPER.addNewNamespace(namespace); } addOrUpdateEntities(ontology, PODD_NAMESPACE_HELPER.getNamespace(namespace)); } private void addOrUpdateEntities(OWLOntology ontology, EnumerableRDFNamespace namespace) { final Set<OWLEntity> entities = ontology.getSignature(); for (OWLEntity entity : entities) { if (entity.getIRI().toString().startsWith(namespace.uri)) { namespace.addElement(entity.getIRI()); } } } private OWLOntologyIRIMapper createOntologyMapper() { final OWLOntologyIRIMapperImpl mapper = new OWLOntologyIRIMapperImpl(); for (File file : ontologyFiles) { final String ontName = file.getName().substring(0, file.getName().indexOf('.')); mapper.addMapping(IRI.create(PODD_URI + ontName), IRI.create(file.toURI())); } return mapper; } private void addToMap(OWLClass owlClass, OWLOntology ontology, Map<OWLClass, Set<OWLAxiom>> map) { final Set<OWLClassAxiom> classAxiomSet = ontology.getAxioms(owlClass); Set<OWLAxiom> set = map.get(owlClass); if (null == set) { set = new HashSet<OWLAxiom>(); } set.addAll(classAxiomSet); map.put(owlClass, set); set.addAll(ontology.getAnnotationAssertionAxioms(owlClass.getIRI())); } private void createPoddConcept(OWLClass owlClass, OWLOntologyManager manager, Set<OWLAxiom> axiomSet, int idx) throws Exception { // OWLOntologyManager manager = ontologyRegistry.getOntologyManager(); final String conceptName = owlClass.getIRI().toString(); logger.info("conceptName=" + conceptName); // try to load the concept and if it doesn't exist create a new one PoddConcept concept = getFirstConcept(conceptDao.loadByLocalName(conceptName)); if (null != concept) { final OWLOntology ontology = concept.getCurrentDefinition(); boolean isChanged = ontologyChanged(axiomSet, concept, ontology, owlClass); if (isChanged) { conceptDao.update(concept); } } else { concept = createConcept(axiomSet, conceptName, manager, owlClass); } if (null != concept) { logger.info("Ingested concept " + idx + ": " + concept.getConceptName()); } } private PoddConcept createConcept(Set<OWLAxiom> axiomSet, String conceptName, OWLOntologyManager manager, OWLClass owlClass) throws Exception { PoddConcept concept = entityFactory.createPoddConcept(adminUser); concept.setConceptName(conceptName); concept.setLabel("Predefined concept: " + conceptName); //IRI baseUri = IRI.create(PODD_MODEL.uri.replace('#', '/') + conceptName + "_Ontology"); IRI baseUri = IRI.create(conceptName + "_Ontology"); final OWLOntology ontology = ontologyHelper.getTimestampedOntology(baseUri); boolean isChanged = ontologyChanged(axiomSet, concept, ontology, owlClass); if (isChanged) { conceptDao.save(concept); } return concept; } private boolean ontologyChanged(Set<OWLAxiom> axiomSet, PoddConcept concept, OWLOntology ontology, OWLClass owlClass) throws OWLOntologyChangeException, DataAccessException { // try { final boolean sameOntology = testSameOntology(ontology, owlClass, axiomSet); if (!sameOntology) { ParameterUtil.wait(TWENTY_MILLISECONDS); ontology.getOWLOntologyManager().addAxioms(ontology, axiomSet); concept.setCurrentDefinition(ontology); return true; } else { return false; } // } finally { // ontology.getOWLOntologyManager().removeOntology(ontology); // } } private boolean testSameOntology(OWLOntology curOntology, OWLClass concept, Set<OWLAxiom> axiomSet) { final Set<OWLAxiom> oldAxiomSet = new HashSet<OWLAxiom>(); oldAxiomSet.addAll(curOntology.getAxioms(concept)); oldAxiomSet.addAll(curOntology.getAnnotationAssertionAxioms(concept.getIRI())); final int oldCount = oldAxiomSet.size(); final int newCount = axiomSet.size(); return oldCount == newCount && oldAxiomSet.containsAll(axiomSet); } private void setupDefaultRepoRoles() { try { saveOrUpdateRole(RepositoryRole.PUBLIC); saveOrUpdateRole(RepositoryRole.REPOSITORY_USER); saveOrUpdateRole(RepositoryRole.PROJECT_CREATOR); saveOrUpdateRole(RepositoryRole.REPOSITORY_ADMINISTRATOR); } catch (DataAccessException e) { throw new RuntimeException(e); } } private void saveOrUpdateRole(RepositoryRole role) throws DataAccessException { RepositoryRole repositoryRole = rrDao.getRepositoryRole(role.getName()); if (null == repositoryRole) { repositoryRole = role; } else { repositoryRole.setDescription(role.getDescription()); } rrDao.saveOrUpdate(repositoryRole); } private void setupDefaultAdministrationSettings() throws DataAccessException { saveOrUpdateAdminSetting(SELF_REGISTRATION_ENABLED); saveOrUpdateAdminSetting(USER_STATUS_ACTIVE); } private void saveOrUpdateAdminSetting(AdministrationSettings setting) throws DataAccessException { AdministrationSettings adminSetting = adminSettingsDao.getAdministrationSetting(setting.getName()); if (null == adminSetting) { adminSetting = setting; } else { adminSetting.setValue(setting.getValue()); } adminSettingsDao.saveOrUpdate(adminSetting); } private <T> T getFirstConcept(CloseableIterator<T> iterator) { try { if (iterator.hasNext()) { return iterator.next(); } else { return null; } } finally { iterator.close(); } } }