/** * Copyright (C) 2012-2013 Selventa, Inc. * * This file is part of the OpenBEL Framework. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The OpenBEL Framework 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the OpenBEL Framework. If not, see <http://www.gnu.org/licenses/>. * * Additional Terms under LGPL v3: * * This license does not authorize you and you are prohibited from using the * name, trademarks, service marks, logos or similar indicia of Selventa, Inc., * or, in the discretion of other licensors or authors of the program, the * name, trademarks, service marks, logos or similar indicia of such authors or * licensors, in any marketing or advertising materials relating to your * distribution of the program or any covered product. This restriction does * not waive or limit your obligation to keep intact all copyright notices set * forth in the program as delivered to you. * * If you distribute the program in whole or in part, or any modified version * of the program, and you assume contractual liability to the recipient with * respect to the program or modified version, then you will indemnify the * authors and licensors of the program for any liabilities that these * contractual assumptions directly impose on those licensors and authors. */ package org.openbel.framework.compiler; import static org.openbel.framework.common.BELUtilities.hasItems; import java.io.IOException; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import org.openbel.framework.common.InvalidArgument; import org.openbel.framework.common.Reportable; import org.openbel.framework.common.index.Equivalence; import org.openbel.framework.common.index.Index; import org.openbel.framework.common.index.ResourceIndex; import org.openbel.framework.common.model.DataFileIndex; import org.openbel.framework.common.model.EquivalenceDataIndex; import org.openbel.framework.common.protonetwork.model.ProtoNetwork; import org.openbel.framework.common.protonetwork.model.ProtoNetworkError; import org.openbel.framework.common.protonetwork.model.NamespaceTable.TableNamespace; import org.openbel.framework.core.df.cache.CacheableResourceService; import org.openbel.framework.core.df.cache.ResolvedResource; import org.openbel.framework.core.df.cache.ResourceType; import org.openbel.framework.core.equivalence.BucketEquivalencer; import org.openbel.framework.core.equivalence.EquivalenceIndexerService; import org.openbel.framework.core.equivalence.EquivalenceMapResolutionFailure; import org.openbel.framework.core.equivalence.EquivalenceResource; import org.openbel.framework.core.equivalence.EquivalenceResourceImpl; import org.openbel.framework.core.equivalence.StatementEquivalencer; import org.openbel.framework.core.equivalence.TermEquivalencer; import org.openbel.framework.core.indexer.IndexingFailure; import org.openbel.framework.core.protocol.ResourceDownloadError; import org.openbel.framework.core.protonetwork.ProtoNetworkDescriptor; import org.openbel.framework.core.protonetwork.ProtoNetworkService; /** * BEL compiler phase two implementation. * * @author Anthony Bargnesi {@code <abargnesi@selventa.com>} */ public final class PhaseTwoImpl implements DefaultPhaseTwo { private final CacheableResourceService cache; private final EquivalenceIndexerService equivalenceIndexerService; private final ProtoNetworkService protoNetworkService; private EquivalenceResource equivs; /** Reporting mechanism for errors, warnings, and output. */ private Reportable reportable; /** * Creates the {@link DefaultPhaseTwo} implementation from the * {@code resourceResolverService}, {@code equivalenceIndexerService}, and * {@code protoNetworkService} services. * * @param cache {@link CacheableResourceService}, the resource resolver * service * @param equivalenceIndexerService {@link EquivalenceIndexerService}, the * equivalence indexer service * @param protoNetworkService {@link ProtoNetworkService}, the proto network * service */ public PhaseTwoImpl( final CacheableResourceService cache, final EquivalenceIndexerService equivalenceIndexerService, final ProtoNetworkService protoNetworkService) { this.cache = cache; this.equivalenceIndexerService = equivalenceIndexerService; this.protoNetworkService = protoNetworkService; } /** * Injects the reporting mechanism. * * @param r {@link Reportable}, the reportable reporting mechanism */ public void setReportable(final Reportable r) { this.reportable = r; } /** * {@inheritDoc} */ @Override public ProtoNetwork stage1Merger( Collection<ProtoNetworkDescriptor> protoNetworkDescriptors) { ProtoNetwork mergedNetwork = null; try { Iterator<ProtoNetworkDescriptor> it = protoNetworkDescriptors.iterator(); // Grab first proto network and iteratively merge the rest. ProtoNetworkDescriptor pnd = it.next(); mergedNetwork = protoNetworkService.read(pnd); while (it.hasNext()) { ProtoNetwork nextPn = protoNetworkService.read(it.next()); protoNetworkService.merge(mergedNetwork, nextPn); } } catch (ProtoNetworkError e) { e.printStackTrace(); Throwable cause = e.getCause(); if (cause != null) e.printStackTrace(); error("Unable to merge proto networks into global network."); } return mergedNetwork; } /** * {@inheritDoc} */ @Override public Set<EquivalenceDataIndex> stage2LoadNamespaceEquivalences() throws EquivalenceMapResolutionFailure { Set<EquivalenceDataIndex> equivalenceDataIndexSet = new HashSet<EquivalenceDataIndex>(); Index resourceIndex = ResourceIndex.INSTANCE.getIndex(); if (hasItems(resourceIndex.getEquivalenceResources())) { for (Equivalence eqResource : resourceIndex .getEquivalenceResources()) { String eqLocation = eqResource.getResourceLocation(); try { ResolvedResource resolved = cache.resolveResource( ResourceType.EQUIVALENCES, eqLocation); DataFileIndex equivalenceIndex = equivalenceIndexerService .indexEquivalence(eqLocation, resolved.getCacheResourceCopy()); equivalenceDataIndexSet.add(new EquivalenceDataIndex( eqResource.getNamespaceResourceLocation() .getResourceLocation(), equivalenceIndex)); } catch (ResourceDownloadError e) { error("Unable to load equivalence resource for location: " + eqLocation); } catch (IndexingFailure e) { error("Unable to load equivalence resource for location: " + eqLocation); } } } return equivalenceDataIndexSet; } /** * {@inheritDoc} */ @Override public int stage3EquivalenceParameters(ProtoNetwork network, Set<EquivalenceDataIndex> indexes) throws IOException { if (indexes == null) { throw new InvalidArgument("indexes", indexes); } // FIXME Better way to subset equivalences, like maybe by domain Set<String> pnNsLocations = new HashSet<String>(); for (TableNamespace tn : network.getNamespaceTable().getNamespaces()) { pnNsLocations.add(tn.getResourceLocation()); } Iterator<EquivalenceDataIndex> indexIt = indexes.iterator(); while (indexIt.hasNext()) { EquivalenceDataIndex index = indexIt.next(); // if proto network does not contain this index, throw it away if (!pnNsLocations.contains(index.getNamespaceResourceLocation())) { indexIt.remove(); } } if (!indexes.isEmpty()) { equivs = new EquivalenceResourceImpl(indexes); equivs.openResources(); BucketEquivalencer be = new BucketEquivalencer(network, equivs); return be.equivalence(); } return 0; } /** * {@inheritDoc} */ @Override public int stage3EquivalenceTerms(ProtoNetwork network) { TermEquivalencer e = new TermEquivalencer(network, equivs); int equivalences = e.equivalence(); try { equivs.closeResources(); } catch (IOException ie) { // Ignore it } return equivalences; } /** * {@inheritDoc} */ @Override public int stage3EquivalenceStatements(ProtoNetwork network) { StatementEquivalencer e = new StatementEquivalencer(network); int equivalences = e.equivalence(); return equivalences; } /** * {@inheritDoc} */ @Override public ProtoNetworkDescriptor stage4WriteEquivalentProtoNetwork( ProtoNetwork protoNetwork, String protoNetworkRoot) { if (protoNetwork == null) { throw new InvalidArgument("protoNetwork", protoNetwork); } if (protoNetworkRoot == null) { throw new InvalidArgument("protoNetworkRoot", protoNetworkRoot); } ProtoNetworkDescriptor protoNetworkDescriptor = null; try { protoNetworkDescriptor = protoNetworkService.write( protoNetworkRoot, protoNetwork); } catch (ProtoNetworkError e) { error("Could not write out equivalent proto network."); } return protoNetworkDescriptor; } /** * Sends an "error" {@link String} to the {@link Reportable} object. * * @param s {@link String} the error message to report on */ private void error(final String s) { reportable.error(s); } }