code: package it.unibz.inf.ontop.protege.action;
  
  /*
   * #%L
   * ontop-protege
   * %%
   * Copyright (C) 2009 - 2013 KRDB Research Centre. Free University of Bozen Bolzano.
   * %%
   * 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%
   */
  
  import com.google.inject.Injector;
  import it.unibz.inf.ontop.shaded.com.google.common.collect.ImmutableList;
  import it.unibz.inf.ontop.dbschema.ImmutableMetadata;
  import it.unibz.inf.ontop.dbschema.MetadataProvider;
  import it.unibz.inf.ontop.dbschema.NamedRelationDefinition;
  import it.unibz.inf.ontop.dbschema.RelationID;
  import it.unibz.inf.ontop.dbschema.impl.CachingMetadataLookup;
  import it.unibz.inf.ontop.dbschema.impl.JDBCMetadataProviderFactory;
  import it.unibz.inf.ontop.model.term.functionsymbol.db.BnodeStringTemplateFunctionSymbol;
  import it.unibz.inf.ontop.protege.core.*;
  import it.unibz.inf.ontop.protege.mapping.DuplicateTriplesMapException;
  import it.unibz.inf.ontop.protege.utils.DialogUtils;
  import it.unibz.inf.ontop.protege.utils.SwingWorkerWithCompletionPercentageMonitor;
  import it.unibz.inf.ontop.spec.mapping.bootstrap.impl.DirectMappingEngine;
  import it.unibz.inf.ontop.spec.mapping.pp.SQLPPTriplesMap;
  import org.protege.editor.core.ui.action.ProtegeAction;
  import org.semanticweb.owlapi.model.OWLDeclarationAxiom;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  import javax.swing.*;
  import java.awt.*;
  import java.awt.event.ActionEvent;
  import java.sql.Connection;
  import java.util.HashMap;
  import java.util.Map;
  import java.util.Set;
  import java.util.concurrent.CancellationException;
  import java.util.concurrent.ExecutionException;
  import java.util.concurrent.atomic.AtomicInteger;
  
  import static it.unibz.inf.ontop.protege.utils.DialogUtils.HTML_TAB;
  
  public class BootstrapAction extends ProtegeAction {
  
  	private static final long serialVersionUID = 8671527155950905524L;
  
  	private static final Logger LOGGER = LoggerFactory.getLogger(BootstrapAction.class);
  
  	private static final String DIALOG_TITLE = "Bootstrapping ontology and mapping";
  
  	@Override
  	public void actionPerformed(ActionEvent evt) {
  
  		OBDAModel obdaModel = OBDAEditorKitSynchronizerPlugin.getCurrentOBDAModel(getEditorKit());
  		OntologyPrefixManager prefixManager = obdaModel.getMutablePrefixManager();
  
  		String defaultBaseIRI = prefixManager.getDefaultIriPrefix()
  				.replace("#", "/");
  
  		JPanel panel = new JPanel();
  		panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
  
  		JLabel baseIriLabel = new JLabel("Base IRI - the prefix " +
  				"to be used for all generated classes and properties: ");
  		baseIriLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
  		panel.add(baseIriLabel);
  
  		panel.add(Box.createRigidArea(new Dimension(10, 10)));
  
  		JTextField baseIriField = new JTextField(defaultBaseIRI);
  		baseIriField.setAlignmentX(Component.LEFT_ALIGNMENT);
  		panel.add(baseIriField);
  
  		panel.add(Box.createRigidArea(new Dimension(20, 20)));
  
  		if (JOptionPane.showOptionDialog(getWorkspace(),
  				panel,
  				DIALOG_TITLE,
  				JOptionPane.OK_CANCEL_OPTION,
  				JOptionPane.QUESTION_MESSAGE,
  				DialogUtils.getOntopIcon(),
  				null,
  				null) != JOptionPane.OK_OPTION)
  			return;
  
  		String baseIri0 = baseIriField.getText().trim();
  		if (baseIri0.contains("#")) {
  			DialogUtils.showPrettyMessageDialog(getWorkspace(),
  					"Base IRIs cannot contain '#':\n" +
  							baseIri0 + " is not a valid base IRI.",
  					DIALOG_TITLE);
  			return;
  		}
  
  		String baseIri = DirectMappingEngine.fixBaseURI(
  				baseIri0.isEmpty() ? defaultBaseIRI : baseIri0);
  		prefixManager.generateUniquePrefixForBootstrapper(baseIri);
  
  		BootstrapWorker worker = new BootstrapWorker(baseIri);
  		worker.execute();
  	}
  
  	private class BootstrapWorker extends SwingWorkerWithCompletionPercentageMonitor<ImmutableList<SQLPPTriplesMap>, Void> {
  
  		private final String baseIri;
  		private final JDBCMetadataProviderFactory metadataProviderFactory;
  		private final DirectMappingEngine directMappingEngine;
  		private final OBDAModel obdaModel;
  
  		private final AtomicInteger currentMappingIndex;
  
  		BootstrapWorker(String baseIri) {
  			super(getWorkspace(),
  					"<html><h3>Bootstrapping ontology and mapping:</h3></html>");
  
  			this.baseIri = baseIri;
  
  			obdaModel = OBDAEditorKitSynchronizerPlugin.getCurrentOBDAModel(getEditorKit());
  
  			Injector injector = obdaModel.getOntopConfiguration().getInjector();
  			this.metadataProviderFactory = injector.getInstance(JDBCMetadataProviderFactory.class);
  			this.directMappingEngine = injector.getInstance(DirectMappingEngine.class);
  
  			this.currentMappingIndex = new AtomicInteger(obdaModel.getTriplesMapManager().size() + 1);
  		}
  
  		@Override
  		protected ImmutableList<SQLPPTriplesMap> doInBackground() throws Exception {
  
  			start("initializing...");
  
  			final ImmutableMetadata metadata;
  
  			try (Connection conn = obdaModel.getDataSource().getConnection()) {
  				MetadataProvider metadataProvider = metadataProviderFactory.getMetadataProvider(conn);
  				ImmutableList<RelationID> relationIds = metadataProvider.getRelationIDs();
  
  				setMaxTicks(relationIds.size() * 2);
  				startLoop(this::getCompletionPercentage, () -> String.format("%d%% completed.", getCompletionPercentage()));
  
  				CachingMetadataLookup lookup = new CachingMetadataLookup(metadataProvider);
  				for (RelationID id : relationIds) {
  					lookup.getRelation(id);
  					tick();
  				}
  				metadata = lookup.extractImmutableMetadata();
  			}
  
  			Map<NamedRelationDefinition, BnodeStringTemplateFunctionSymbol> bnodeTemplateMap = new HashMap<>();
  
  			ImmutableList.Builder<SQLPPTriplesMap> builder = ImmutableList.builder();
  			for (NamedRelationDefinition relation : metadata.getAllRelations()) {
  				builder.addAll(directMappingEngine
  						.getMapping(relation, baseIri, bnodeTemplateMap, currentMappingIndex));
  				tick();
  			}
  
  			endLoop("");
  			ImmutableList<SQLPPTriplesMap> triplesMaps = builder.build();
  			end();
  			return triplesMaps;
  		}
  
  		@Override
  		public void done() {
  			try {
  				ImmutableList<SQLPPTriplesMap> triplesMaps = complete();
  				// TODO: move back to doInBackground?
  				Set<OWLDeclarationAxiom> axioms = obdaModel.insertTriplesMaps(triplesMaps, true);
  				DialogUtils.showInfoDialog(getWorkspace(),
  						"<html><h3>Bootstrapping the ontology and mapping is complete.</h3><br>" +
  								HTML_TAB + "<b>" + triplesMaps.size() + "</b> triples maps inserted into the mapping.<br>" +
  								HTML_TAB + "<b>" + axioms.size() + "</b> declaration axioms (re)inserted into the ontology.<br></html>",
  						DIALOG_TITLE);
  			}
  			catch (DuplicateTriplesMapException e) {
  				LOGGER.error("Internal error:", e);
  			}
  			catch (CancellationException | InterruptedException e) {
  				DialogUtils.showCancelledActionDialog(getWorkspace(), DIALOG_TITLE);
  			}
  			catch (ExecutionException e) {
  				DialogUtils.showErrorDialog(getWorkspace(), DIALOG_TITLE, DIALOG_TITLE + " error.", LOGGER, e, obdaModel.getDataSource());
  			}
  		}
  	}
  
  
  	@Override
  	public void initialise() { /* NO-OP */ }
  
  	@Override
  	public void dispose() {/* NO-OP */ }
  
  }
  