/* * Copyright 2015 * Ubiquitous Knowledge Processing (UKP) Lab and FG Language Technology * Technische Universität Darmstadt * * 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. */ package de.tudarmstadt.ukp.clarin.webanno.api.dao.migration; import static de.tudarmstadt.ukp.clarin.webanno.api.WebAnnoConst.COREFERENCE_RELATION_FEATURE; import static de.tudarmstadt.ukp.clarin.webanno.api.WebAnnoConst.COREFERENCE_TYPE_FEATURE; import java.util.Arrays; import javax.annotation.Resource; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.Query; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.uima.cas.CAS; import org.springframework.context.SmartLifecycle; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.DefaultTransactionDefinition; /** * WebAnno versions until 3.0.0 set the feature types of Coreference features "referenceType" * and "referenceRelation" wrongly to "de.tudarmstadt.ukp.dkpro.core.api.coref.type.Coreference" - * it should be "uima.cas.String" */ public class FixCoreferenceFeatures implements SmartLifecycle { private final Logger log = LoggerFactory.getLogger(getClass()); private boolean running = false; @PersistenceContext private EntityManager entityManager; @Resource(name = "transactionManager") private JpaTransactionManager txManager; @Override public boolean isRunning() { return running; } @Override public void start() { running = true; doMigration(); } @Override public void stop() { running = false; } @Override public int getPhase() { return Integer.MIN_VALUE; } @Override public boolean isAutoStartup() { return true; } @Override public void stop(Runnable aCallback) { stop(); aCallback.run(); } private void doMigration() { DefaultTransactionDefinition def = new DefaultTransactionDefinition(); def.setName("migrationRoot"); def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); TransactionStatus status = null; try { status = txManager.getTransaction(def); Query q = entityManager.createQuery( "UPDATE AnnotationFeature \n" + "SET type = :fixedType \n" + "WHERE type = :oldType \n" + "AND name in (:featureNames)"); // This condition cannot be applied: // "AND layer.type = :layerType" // q.setParameter("layerType", CHAIN_TYPE); // http://stackoverflow.com/questions/16506759/hql-is-generating-incomplete-cross-join-on-executeupdate // However, the risk that the migration upgrades the wrong featuers is still very low // even without this additional condition q.setParameter("featureNames", Arrays.asList(COREFERENCE_RELATION_FEATURE, COREFERENCE_TYPE_FEATURE)); q.setParameter("oldType", "de.tudarmstadt.ukp.dkpro.core.api.coref.type.Coreference"); q.setParameter("fixedType", CAS.TYPE_NAME_STRING); int changed = q.executeUpdate(); if (changed > 0) { log.info("DATABASE UPGRADE PERFORMED: [" + changed + "] coref chain features had their type fixed"); } txManager.commit(status); } finally { if (status != null && !status.isCompleted()) { txManager.rollback(status); } } } }