Java tutorial
/* * #%L * Protempa Protege Knowledge Source Backend * %% * Copyright (C) 2012 - 2013 Emory University * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ package org.protempa.backend.ksb.protege; import edu.stanford.smi.protege.event.ProjectEvent; import edu.stanford.smi.protege.event.ProjectListener; import edu.stanford.smi.protege.model.Cls; import edu.stanford.smi.protege.model.Instance; import edu.stanford.smi.protege.model.Slot; import org.apache.commons.lang3.ArrayUtils; import org.drools.util.StringUtils; import org.protempa.AbstractionDefinition; import org.protempa.ContextDefinition; import org.protempa.KnowledgeSourceReadException; import org.protempa.PropositionDefinition; import org.protempa.TemporalPropositionDefinition; import org.protempa.TermSubsumption; import org.protempa.valueset.ValueSet; import org.protempa.backend.AbstractCommonsKnowledgeSourceBackend; import org.protempa.backend.BackendInitializationException; import org.protempa.backend.BackendInstanceSpec; import org.protempa.backend.KnowledgeSourceBackendInitializationException; import org.protempa.proposition.value.AbsoluteTimeUnit; import org.protempa.proposition.value.RelativeHourUnit; import org.protempa.proposition.value.Unit; import org.protempa.proposition.value.ValueType; import org.protempa.query.And; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Queue; import java.util.Set; import java.util.logging.Level; import org.protempa.ProtempaUtil; /** * Abstract class for converting a Protege knowledge base into a PROTEMPA * knowledge base. * * @author Andrew Post */ public abstract class ProtegeKnowledgeSourceBackend extends AbstractCommonsKnowledgeSourceBackend implements ProjectListener { private ConnectionManager cm; private Units units; private InstanceConverterFactory instanceConverterFactory; private static enum Units { ABSOLUTE(AbsoluteTimeUnit.class), RELATIVE_HOURS(RelativeHourUnit.class); private Class<? extends Unit> unitClass; Units(Class<? extends Unit> unitClass) { this.unitClass = unitClass; } Class<? extends Unit> getUnitClass() { return this.unitClass; } }; protected ProtegeKnowledgeSourceBackend() { } @Override public void initialize(BackendInstanceSpec config) throws BackendInitializationException { super.initialize(config); if (this.cm == null) { ConnectionManager pcm = initConnectionManager(config); pcm.init(); this.cm = pcm; this.instanceConverterFactory = new InstanceConverterFactory(pcm); } } abstract ConnectionManager initConnectionManager(BackendInstanceSpec configuration) throws KnowledgeSourceBackendInitializationException; ConnectionManager getConnectionManager() { return this.cm; } protected void initUnits(String unitsStr) throws KnowledgeSourceBackendInitializationException { if (unitsStr != null) { try { this.units = Units.valueOf(unitsStr); } catch (Exception e) { throw new KnowledgeSourceBackendInitializationException("Invalid units supplied: " + unitsStr); } } else { Util.logger().fine("No UNITS supplied, using ABSOLUTE"); } if (this.units == null) { this.units = Units.ABSOLUTE; } } @Override public void close() { if (this.cm != null) { this.cm.close(); this.cm = null; } if (this.instanceConverterFactory != null) { this.instanceConverterFactory.reset(); this.instanceConverterFactory = null; } } @Override public PropositionDefinition readPropositionDefinition(String name) throws KnowledgeSourceReadException { Instance instance = this.cm.getInstance(name); if (instance != null) { PropositionConverter converter = this.instanceConverterFactory.getInstance(instance); assert converter != null : "no converter for proposition definintion " + name; return converter.convert(instance, this); } else { return null; } } @Override public List<PropositionDefinition> readPropositionDefinitions(String[] ids) throws KnowledgeSourceReadException { List<PropositionDefinition> result = new ArrayList<>(); for (String id : ids) { PropositionDefinition pd = readPropositionDefinition(id); if (pd != null) { result.add(pd); } } return result; } @Override public List<AbstractionDefinition> readAbstractionDefinitions(String[] ids) throws KnowledgeSourceReadException { List<AbstractionDefinition> result = new ArrayList<>(); for (String id : ids) { AbstractionDefinition ad = readAbstractionDefinition(id); if (ad != null) { result.add(ad); } } return result; } @Override public List<ContextDefinition> readContextDefinitions(String[] ids) throws KnowledgeSourceReadException { List<ContextDefinition> result = new ArrayList<>(); for (String id : ids) { ContextDefinition cd = readContextDefinition(id); if (cd != null) { result.add(cd); } } return result; } @Override public List<TemporalPropositionDefinition> readTemporalPropositionDefinitions(String[] ids) throws KnowledgeSourceReadException { List<TemporalPropositionDefinition> result = new ArrayList<>(); for (String id : ids) { TemporalPropositionDefinition tpd = readTemporalPropositionDefinition(id); if (tpd != null) { result.add(tpd); } } return result; } @Override public AbstractionDefinition readAbstractionDefinition(String name) throws KnowledgeSourceReadException { Instance instance = this.cm.getInstance(name); AbstractionConverter ac = this.instanceConverterFactory.getAbstractionInstance(instance); if (ac == null) { return null; } else { return ac.convert(instance, this); } } @Override public String[] getPropositionsByTerm(String termId) throws KnowledgeSourceReadException { return collectAssociatedNames(termId, "termProposition"); } @Override public List<String> getPropositionsByTermSubsumption(And<TermSubsumption> termIds) throws KnowledgeSourceReadException { List<String> result = new ArrayList<>(); List<Set<String>> propIdSets = new ArrayList<>(); Slot termPropositionSlot = this.cm.getSlot("termProposition"); // collects the set of proposition IDs for each term subsumption for (TermSubsumption ts : termIds.getAnded()) { Set<String> subsumpPropIds = new HashSet<>(); for (String termId : ts.getTerms()) { Instance termInstance = this.cm.getInstance(termId); if (termInstance != null) { Collection<?> props = cm.getOwnSlotValues(termInstance, termPropositionSlot); Iterator<?> it = props.iterator(); while (it.hasNext()) { Instance prop = (Instance) it.next(); subsumpPropIds.add(prop.getName()); } } } propIdSets.add(subsumpPropIds); } Set<String> matchingPropIds = org.arp.javautil.collections.Collections.intersection(propIdSets); result.addAll(matchingPropIds); return result; } /** * Returns the Cls from Protege if a matching Cls is found with the given * ancestor * * @param name Name of the class to fetch * @param superClass name of the anscestor * @return A Cls containing the given class name * @throws KnowledgeSourceReadException */ private Cls readClass(String name, String superClass) throws KnowledgeSourceReadException { Cls cls = this.cm.getCls(name); Cls superCls = this.cm.getCls(superClass); if (cls != null && cls.hasSuperclass(superCls)) { return cls; } else { return null; } } private String[] collectAssociatedNames(String id, String slotName) throws KnowledgeSourceReadException { Instance instance = cm.getInstance(id); return collectAssociatedInstanceNames(instance, slotName); } private String[] collectAssociatedInstanceNames(Instance instance, String slotName) throws KnowledgeSourceReadException { String[] result; if (instance != null) { Collection<Instance> children = (Collection<Instance>) cm.getOwnSlotValues(instance, slotName); result = collectInstanceNames(children); } else { result = StringUtils.EMPTY_STRING_ARRAY; } return result; } private String[] collectInstanceNames(Collection<Instance> instances) { String[] result = new String[instances.size()]; int i = 0; for (Iterator<?> itr = instances.iterator(); itr.hasNext();) { Instance child = (Instance) itr.next(); result[i++] = child.getName(); } return result; } /* * PROJECT CHANGED EVENTS. Protege calls projectClosed() when a remote * project has changed. */ @Override public void formChanged(ProjectEvent arg0) { this.instanceConverterFactory.reset(); fireKnowledgeSourceBackendUpdated(); } @Override public void projectClosed(ProjectEvent arg0) { this.instanceConverterFactory.reset(); fireKnowledgeSourceBackendUpdated(); } @Override public void projectSaved(ProjectEvent arg0) { this.instanceConverterFactory.reset(); fireKnowledgeSourceBackendUpdated(); } @Override public void runtimeClsWidgetCreated(ProjectEvent arg0) { this.instanceConverterFactory.reset(); fireKnowledgeSourceBackendUpdated(); } Unit parseUnit(String protegeUnitStr) { switch (this.units) { case ABSOLUTE: return Util.ABSOLUTE_DURATION_MULTIPLIER.get(protegeUnitStr); case RELATIVE_HOURS: return Util.RELATIVE_HOURS_DURATION_MULTIPLIER.get(protegeUnitStr); default: assert false : this.units; return null; } } @Override public ValueSet readValueSet(String id) throws KnowledgeSourceReadException { Cls cls = readClass(id, "Value"); if (cls == null) { return null; } else { ValueType valueType = Util.parseValueSet(cls); assert valueType != null : "Could not find value type for " + id; return Util.parseValueSet(cls, valueType, cm, this); } } @Override public String[] readAbstractedInto(String propId) throws KnowledgeSourceReadException { Instance instance = this.cm.getInstance(propId); Slot abstractedIntoSlot = this.cm.getSlot("abstractedInto"); Collection<Instance> abstractedIntos = (Collection<Instance>) this.cm.getOwnSlotValues(instance, abstractedIntoSlot); String[] result = new String[abstractedIntos.size()]; int i = 0; for (Instance inst : abstractedIntos) { result[i++] = inst.getName(); } return result; } @Override public String[] readIsA(String propId) throws KnowledgeSourceReadException { Instance instance = this.cm.getInstance(propId); Slot isASlot = this.cm.getSlot("isA"); Collection<Instance> isAs = (Collection<Instance>) this.cm.getOwnSlotValues(instance, isASlot); String[] result = new String[isAs.size()]; int i = 0; for (Instance inst : isAs) { result[i++] = inst.getName(); } return result; } @Override public ContextDefinition readContextDefinition(String id) throws KnowledgeSourceReadException { return null; } @Override public TemporalPropositionDefinition readTemporalPropositionDefinition(String name) throws KnowledgeSourceReadException { Instance instance = this.cm.getInstance(name); TemporalPropositionConverter ac = this.instanceConverterFactory.getTemporalPropositionInstance(instance); if (ac == null) { return null; } else { return ac.convert(instance, this); } } @Override public String[] readInduces(String propId) throws KnowledgeSourceReadException { return ArrayUtils.EMPTY_STRING_ARRAY; } @Override public String[] readSubContextOfs(String propId) throws KnowledgeSourceReadException { return ArrayUtils.EMPTY_STRING_ARRAY; } @Override public Set<String> getKnowledgeSourceSearchResults(String searchKey) throws KnowledgeSourceReadException { return this.cm.searchInstancesContainingKey(searchKey); } @Override public Collection<String> collectPropIdDescendantsUsingAllNarrower(boolean inDataSourceOnly, String[] propIds) throws KnowledgeSourceReadException { ProtempaUtil.checkArrayForNullElement(propIds, "propIds"); return collectPropDescendantsInt(inDataSourceOnly, true, propIds); } @Override public Collection<PropositionDefinition> collectPropDefDescendantsUsingAllNarrower(boolean inDataSourceOnly, String[] propIds) throws KnowledgeSourceReadException { ProtempaUtil.checkArrayForNullElement(propIds, "propIds"); Collection<String> resultPropIds = collectPropDescendantsInt(inDataSourceOnly, true, propIds); List<PropositionDefinition> result = new ArrayList<>(resultPropIds.size()); for (String propId : resultPropIds) { result.add(readPropositionDefinition(propId)); } return result; } @Override public Collection<String> collectPropIdDescendantsUsingInverseIsA(String[] propIds) throws KnowledgeSourceReadException { ProtempaUtil.checkArrayForNullElement(propIds, "propIds"); return collectPropDescendantsInt(false, false, propIds); } @Override public Collection<PropositionDefinition> collectPropDefDescendantsUsingInverseIsA(String[] propIds) throws KnowledgeSourceReadException { ProtempaUtil.checkArrayForNullElement(propIds, "propIds"); Collection<String> resultPropIds = collectPropDescendantsInt(false, false, propIds); List<PropositionDefinition> result = new ArrayList<>(resultPropIds.size()); for (String propId : resultPropIds) { result.add(readPropositionDefinition(propId)); } return result; } private Collection<String> collectPropDescendantsInt(boolean inDataSourceOnly, boolean narrower, String[] propIds) throws KnowledgeSourceReadException { assert propIds != null : "propIds cannot be null"; Slot inverseIsASlot = this.cm.getSlot("inverseIsA"); Slot abstractedFromSlot = this.cm.getSlot("abstractedFrom"); Slot inDataSourceSlot = this.cm.getSlot("inDataSource"); Set<String> result = new HashSet<>(); Queue<Instance> queue = new LinkedList<>(); for (String propId : propIds) { Instance instance = this.cm.getInstance(propId); if (instance == null) { throw new KnowledgeSourceReadException("unknown proposition id " + propId); } else { queue.add(instance); } } while (!queue.isEmpty()) { Instance instance = queue.poll(); if (inDataSourceOnly) { Boolean inDataSource = (Boolean) this.cm.getOwnSlotValue(instance, inDataSourceSlot); if (inDataSource != null && inDataSource.booleanValue()) { result.add(instance.getName()); } } else { result.add(instance.getName()); } Collection<?> inverseIsAs = this.cm.getOwnSlotValues(instance, inverseIsASlot); for (Object obj : inverseIsAs) { queue.add((Instance) obj); } Collection<?> abstractedFroms = narrower ? this.cm.getOwnSlotValues(instance, abstractedFromSlot) : Collections.emptyList(); for (Object obj : abstractedFroms) { queue.add((Instance) obj); } } return result; } }