package org.molgenis.animaldb.commonservice; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.text.ParseException; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import org.molgenis.animaldb.AnimalDbFile; import org.molgenis.animaldb.CustomLabelFeature; import org.molgenis.animaldb.NamePrefix; import org.molgenis.auth.MolgenisUser; import org.molgenis.batch.MolgenisBatch; import org.molgenis.batch.MolgenisBatchEntity; import org.molgenis.core.MolgenisEntity; import org.molgenis.core.OntologyTerm; import org.molgenis.framework.db.Database; import org.molgenis.framework.db.DatabaseException; import org.molgenis.framework.db.Query; import org.molgenis.framework.db.QueryRule; import org.molgenis.framework.db.QueryRule.Operator; import org.molgenis.organization.Investigation; import org.molgenis.pheno.Category; import org.molgenis.pheno.Individual; import org.molgenis.pheno.Location; import org.molgenis.pheno.Measurement; import org.molgenis.pheno.ObservableFeature; import org.molgenis.pheno.ObservationTarget; import org.molgenis.pheno.ObservedValue; import org.molgenis.pheno.Panel; import org.molgenis.protocol.Protocol; import org.molgenis.protocol.ProtocolApplication; import org.molgenis.util.Tuple; import decorators.NameConvention; import filehandling.generic.PerformUpload; /** * @author erikroos * * Changelog <li>MS: Added constants to replace the String values that * lead to so many typos. Can't we autogenerate all these services?</li> */ public class CommonService { public static final String ANIMAL = "Animal"; public static final String ACTIVE = "Active"; public static final String LOCATION = "Location"; public static final String PANEL = "Panel"; protected static Database db; private static int protAppCounter = 0; // for generating unique protocol // application names private transient Logger logger = Logger.getLogger(CommonService.class); protected static Map<Integer, String> observationTargetNameMap = null; // --- Stuff for Singleton design pattern protected static CommonService instance = null; protected CommonService() { } public static CommonService getInstance() { if (instance == null) { instance = new CommonService(); } return instance; } // --- public Database getDatabase() { return db; } public void setDatabase(Database db) { CommonService.db = db; } /** * Helper funtion to upload Dec application files. Note the use of name and * uniquePostfix! * * @param name * @param uniquePostfix * @param request * @throws Exception */ public String addAnimalDbFile(String name, String uniquePostfix, Tuple request, boolean overwriteExisting) throws Exception { // DEC application PDF File fileFromRequest = request.getFile(name.toLowerCase()); if (fileFromRequest == null) { throw new FileNotFoundException("No " + name.toLowerCase() + " selected"); } String originalFileName = request.getString(name.toLowerCase() + "OriginalFileName"); if (!originalFileName.contains(".")) { throw new FileNotFoundException("The uploaded file does not have an extension"); } String originalFileExt = originalFileName.substring(originalFileName.lastIndexOf(".") + 1); String fileName = name.toLowerCase() + "_" + NameConvention.escapeFileName(uniquePostfix); // use // DEC // name // to // make // it // 'unique' // if the name exists: delete the old one! List<AnimalDbFile> afList = db.find(AnimalDbFile.class, new QueryRule(AnimalDbFile.NAME, Operator.EQUALS, fileName)); if (afList.size() == 1) // if there are more: you are in really big // trouble because name is unique constraint! { if (overwriteExisting) { db.remove(afList.get(0)); } else { throw new FileNotFoundException("File already exists, overwriting not allowed!"); } } AnimalDbFile file = new AnimalDbFile(); file.setName(fileName); file.setExtension(originalFileExt); db.add(file); PerformUpload.doUpload(db, file, fileFromRequest, true); return fileName; } /** * Retrieve an investigation id based on an investigation name. Returns -1 * if none found. * * @param invName * investigation name * @return id of the investigation * @throws DatabaseException * @throws ParseException */ public int getInvestigationId(String invName) throws DatabaseException, ParseException { Query<Investigation> q = db.query(Investigation.class); q.addRules(new QueryRule(Investigation.NAME, Operator.EQUALS, invName)); List<Investigation> invList = q.find(); if (invList.size() > 0) { return invList.get(0).getId(); } else { return -1; } } /** * Gets the name of the first investigation owned by the user with name * 'userName'. Returns null if no investigations found. * * @param userId * @return * @throws DatabaseException * @throws ParseException */ public String getOwnUserInvestigationName(String userName) { Query<Investigation> q = db.query(Investigation.class); q.addRules(new QueryRule(Investigation.OWNS_NAME, Operator.EQUALS, userName)); List<Investigation> invList; try { invList = q.find(); } catch (Exception e) { return null; } if (invList.size() > 0) { return invList.get(0).getName(); } else { return null; } } /** * Gets the names of all the investigations owned by the user with name * 'userName'. Returns null if no investigation found. * * @param userName * @return * @throws DatabaseException * @throws ParseException */ public List<String> getOwnUserInvestigationNames(String userName) { Query<Investigation> q = db.query(Investigation.class); q.addRules(new QueryRule(Investigation.OWNS_NAME, Operator.EQUALS, userName)); List<Investigation> invList; List<String> returnList = new ArrayList<String>(); try { invList = q.find(); } catch (Exception e) { return null; } if (invList != null && invList.size() > 0) { for (Investigation inv : invList) { returnList.add(inv.getName()); } } else { return null; } return returnList; } /** * Gets the investigations owned, readable or writable by the user with name * 'userName'. TODO: also take groups into account. * * @param userName * @return */ public List<Investigation> getAllUserInvestigations(String userName) { Query<Investigation> q = db.query(Investigation.class); q.addRules(new QueryRule(Investigation.OWNS_NAME, Operator.EQUALS, userName)); q.addRules(new QueryRule(Operator.OR)); q.addRules(new QueryRule(Investigation.CANREAD_NAME, Operator.EQUALS, userName)); q.addRules(new QueryRule(Operator.OR)); q.addRules(new QueryRule(Investigation.CANREAD_NAME, Operator.EQUALS, "AllUsers")); // FIXME // evil!!! q.addRules(new QueryRule(Operator.OR)); q.addRules(new QueryRule(Investigation.CANWRITE_NAME, Operator.EQUALS, userName)); List<Investigation> invList; try { invList = q.find(); } catch (Exception e) { return null; } return invList; } /** * Gets the names of the investigations owned, readable or writable by the * user with name 'userName'. * * @param userName * @return */ public List<String> getAllUserInvestigationNames(String userName) { List<String> returnList = new ArrayList<String>(); List<Investigation> invList = getAllUserInvestigations(userName); if (invList != null) { for (Investigation inv : invList) { if (!returnList.contains(inv.getName())) { returnList.add(inv.getName()); } } } return returnList; } /** * Gets the Ids of the investigations owned, readable or writable by the * user with name 'userName'. * * @param userName * @return */ public List<Integer> getAllUserInvestigationIds(String userName) { List<Integer> returnList = new ArrayList<Integer>(); List<Investigation> invList = getAllUserInvestigations(userName); if (invList != null) { for (Investigation inv : invList) { if (!returnList.contains(inv.getName())) { returnList.add(inv.getId()); } } } return returnList; } /** * Gets the names of the investigation owned or writable by the user with * name 'userName'. * * @param userName * @return * @throws DatabaseException * @throws ParseException */ public List<String> getWritableUserInvestigationNames(String userName) { Query<Investigation> q = db.query(Investigation.class); q.addRules(new QueryRule(Investigation.OWNS_NAME, Operator.EQUALS, userName)); q.addRules(new QueryRule(Operator.OR)); q.addRules(new QueryRule(Investigation.CANWRITE_NAME, Operator.EQUALS, userName)); List<String> returnList = new ArrayList<String>(); List<Investigation> invList; try { invList = q.find(); } catch (Exception e) { return null; } for (Investigation inv : invList) { returnList.add(inv.getName()); } return returnList; } /** * Retrieve an observation target by id. Gives back null if not found. * */ public ObservationTarget getObservationTargetById(int targetId) throws DatabaseException, ParseException { return db.findById(ObservationTarget.class, targetId); } /** * Retrieve an observation target by name. Gives back null if not found. * */ public ObservationTarget getObservationTargetByName(String targetName) throws DatabaseException, ParseException { if (db.query(ObservationTarget.class).eq(ObservationTarget.NAME, targetName).find().isEmpty()) { return null; } else { return db.query(ObservationTarget.class).eq(ObservationTarget.NAME, targetName).find().get(0); } } /** * Retrieve a location by id * * @param locationId * the id to look for * @return a Location entity with Id locationId * @throws DatabaseException * @throws ParseException */ public Location getLocationById(int locationId) throws DatabaseException, ParseException { return db.findById(Location.class, locationId); } /** * Retrieve an individual by id * * @param individualId * the id to look for * @return an Individual entity with Id individualId * @throws DatabaseException * @throws ParseException */ public Individual getIndividualById(int individualId) throws DatabaseException, ParseException { return db.findById(Individual.class, individualId); } /** * Get the Id of a given ObservationTarget, searching by name * * @param targetName * the name of the ObservationTarget element to look for * @return an integer matching the id of the ObservationTarget element, or * -1 if none was found */ public int getObservationTargetId(String targetName) { ObservationTarget tmpTarget; try { tmpTarget = ObservationTarget.findByName(db, targetName); } catch (Exception e) { return -1; } if (tmpTarget != null) { return tmpTarget.getId(); } else { return -1; } } /** * Creates an Individual but does NOT add it to the database. * * @param investigationId * id to use for new Individual * @return new Individual * @throws DatabaseException * @throws ParseException * @throws IOException */ public Individual createIndividual(int investigationId, String individualName, int userId) throws DatabaseException, ParseException, IOException { Individual newInd = new Individual(); newInd.setInvestigation_Id(investigationId); newInd.setName(individualName); // placeholder newInd.setOwns(userId); return newInd; } /** * Creates an Individual but does NOT add it to the database. Uses * Investigation and User Names so it can be used with lists. * * @param investigationName * @param individualName * @param userName * @return * @throws DatabaseException * @throws ParseException * @throws IOException */ public Individual createIndividual(String investigationName, String individualName, String userName) throws DatabaseException, ParseException, IOException { Individual newInd = new Individual(); newInd.setInvestigation_Name(investigationName); newInd.setName(individualName); // placeholder newInd.setOwns_Name(userName); return newInd; } /** * Return a list of all observation targets of a certain type in the * investigations with ID's in investigationIds or in the System * investigation. If desired, filtered down to only the currently active * ones. * * @param type * : observation target type (Individual, Panel, Location etc.) * to filter on, may be null * @param isActive * : whether or not to filter on Active state (endtime is null) * @return List of ObservationTargets, if desired of a certain type * @throws DatabaseException * @throws ParseException */ @SuppressWarnings("unchecked") public List<String> getAllObservationTargetNames(String type, boolean isActive, List<String> investigationNames) throws DatabaseException, ParseException { List<String> returnList = new ArrayList<String>(); if (investigationNames == null) { investigationNames = new ArrayList<String>(); } if (!investigationNames.contains("System")) { investigationNames.add("System"); } @SuppressWarnings("rawtypes") Class targetClass = db.getClassForName("ObservationTarget"); if (type != null) { targetClass = db.getClassForName(type); } if (isActive == false) { Query<ObservationTarget> targetQuery = db.query(targetClass); targetQuery.addRules(new QueryRule(ObservationTarget.INVESTIGATION_NAME, Operator.IN, investigationNames)); targetQuery.addRules(new QueryRule(Operator.SORTASC, ObservationTarget.NAME)); List<ObservationTarget> targetList = targetQuery.find(); for (ObservationTarget target : targetList) { returnList.add(target.getName()); } return returnList; } else { // Find 'Active' target names Query<ObservedValue> valueQuery = db.query(ObservedValue.class); valueQuery.addRules(new QueryRule(ObservedValue.FEATURE_NAME, Operator.EQUALS, "Active")); valueQuery.addRules(new QueryRule(ObservedValue.ENDTIME, Operator.EQUALS, null)); valueQuery.addRules(new QueryRule(ObservedValue.INVESTIGATION_NAME, Operator.IN, investigationNames)); List<ObservedValue> valueList = valueQuery.find(); List<String> activeNameList = new ArrayList<String>(); for (ObservedValue value : valueList) { if (!activeNameList.contains(value.getTarget_Name())) { activeNameList.add(value.getTarget_Name()); } } // Find target names of right type List<String> typeNameList = new ArrayList<String>(); Query<ObservationTarget> targetQuery = db.query(targetClass); targetQuery.addRules(new QueryRule(ObservationTarget.INVESTIGATION_NAME, Operator.IN, investigationNames)); targetQuery.addRules(new QueryRule(Operator.SORTASC, ObservationTarget.NAME)); List<ObservationTarget> targetList = targetQuery.find(); for (ObservationTarget target : targetList) { if (!typeNameList.contains(target.getName())) { typeNameList.add(target.getName()); } } // Keep overlap and return corresponding targets typeNameList.retainAll(activeNameList); return typeNameList; } } /** * Returns all ObservedValues for the given Measurement ID, sorted * descending on 'time'. * * @param measurementId * @return * @throws DatabaseException * @throws ParseException */ public List<ObservedValue> getAllObservedValues(int measurementId, List<Integer> investigationIds) throws DatabaseException, ParseException { Query<ObservedValue> q = db.query(ObservedValue.class); q.addRules(new QueryRule(ObservedValue.FEATURE, Operator.EQUALS, measurementId)); q.addRules(new QueryRule(ObservedValue.INVESTIGATION, Operator.IN, investigationIds)); q.addRules(new QueryRule(Operator.SORTDESC, ObservedValue.TIME)); return q.find(); } /** * Returns all ObservationTargets in the Investigations with the given names * * @return list of observation targets * @throws DatabaseException */ public List<ObservationTarget> getAllObservationTargets(List<String> investigationNames) { try { return db.query(ObservationTarget.class).in(ObservationTarget.INVESTIGATION_NAME, investigationNames) .find(); } catch (Exception e) { return new ArrayList<ObservationTarget>(); } } public List<MolgenisBatch> getAllBatches() { try { List<MolgenisBatch> batches = db.find(MolgenisBatch.class); return batches; } catch (DatabaseException dbe) { return new ArrayList<MolgenisBatch>(); } } /** * Get the ID's of all targets in the batch as strings. * * @param id * : id of the batch * @return */ public List<String> getTargetsFromBatch(int id) { List<String> returnList = new ArrayList<String>(); Query<MolgenisBatchEntity> q = db.query(MolgenisBatchEntity.class); q.addRules(new QueryRule(MolgenisBatchEntity.BATCH, Operator.EQUALS, id)); // TODO: check if type is ObservationTarget? Is type stored anyway? try { List<MolgenisBatchEntity> entities = q.find(); for (MolgenisBatchEntity m : entities) { returnList.add(m.getObjectId().toString()); } } catch (Exception e) { // Do nothing, return empty list } return returnList; } /** * Returns a list of ObservationTargets belonging to the ID's provided. * Returns an empty list when no ID's are passed. * * @param idList * : the ID's of the desired ObservationTargets * @return * @throws DatabaseException * @throws ParseException */ public List<ObservationTarget> getObservationTargets(List<String> nameList) throws DatabaseException, ParseException { if (nameList.size() > 0) { Query<ObservationTarget> targetQuery = db.query(ObservationTarget.class); targetQuery.addRules(new QueryRule(ObservationTarget.NAME, Operator.IN, nameList)); targetQuery.addRules(new QueryRule(Operator.SORTASC, ObservationTarget.NAME)); return targetQuery.find(); } else { return new ArrayList<ObservationTarget>(); } } /** * Get the name or -if existent- custom label for the ObservationTarget. * * @param targetId * @return * @throws DatabaseException * @throws ParseException */ public String getObservationTargetLabel(int targetId) throws DatabaseException, ParseException { if (observationTargetNameMap == null) { throw new DatabaseException("Target label map not initialized"); // return getObservationTargetById(targetId).getName(); } if (observationTargetNameMap.get(targetId) != null) { return observationTargetNameMap.get(targetId); } return getObservationTargetById(targetId).getName(); } /** * Returns a list of Individuals belonging to the ID's provided. Returns an * empty list when no ID's are passed. * * @param idList * : the ID's of the desired Individuals * @return * @throws DatabaseException * @throws ParseException */ public List<Individual> getIndividuals(List<Integer> idList) throws DatabaseException, ParseException { if (idList.size() > 0) { Query<Individual> targetQuery = db.query(Individual.class); targetQuery.addRules(new QueryRule(Individual.ID, Operator.IN, idList)); return targetQuery.find(); } else { return new ArrayList<Individual>(); } } /** * Creates a Location and adds it to the database. */ public int makeLocation(String investigationName, String locationName, String userName) throws DatabaseException, ParseException, IOException { Location locationToAdd = new Location(); locationToAdd.setName(locationName); locationToAdd.setInvestigation_Name(investigationName); locationToAdd.setOwns_Name(userName); db.add(locationToAdd); return locationToAdd.getId(); } public List<Location> getAllLocations() throws DatabaseException { return db.find(Location.class); } /** * Creates a Panel and adds it to the database. */ public int makePanel(String investigationName, String panelName, String userName) throws DatabaseException, IOException, ParseException { Panel newGroup = new Panel(); newGroup.setName(panelName); newGroup.setInvestigation_Name(investigationName); newGroup.setOwns_Name(userName); db.add(newGroup); return newGroup.getId(); } /** * Creates a Panel but does NOT add it to the database. Uses Investigation * and User Names so it can be used with lists. */ public Panel createPanel(String investigationName, String panelName, String userName) throws DatabaseException, IOException, ParseException { if (panelName == null) { throw new DatabaseException("Panel name cannot be null!"); } Panel newGroup = new Panel(); newGroup.setName(panelName); newGroup.setInvestigation_Name(investigationName); newGroup.setOwns_Name(userName); return newGroup; } /** * Returns a list of all Panels that have been given a certain mark using a * 'TypeOfGroup' ObservedValue. * * @param mark * @return * @throws DatabaseException * @throws ParseException */ public List<ObservationTarget> getAllMarkedPanels(String mark, List<String> investigationNames) throws DatabaseException, ParseException { List<String> panelNameList = new ArrayList<String>(); Query<ObservedValue> valueQuery = db.query(ObservedValue.class); valueQuery.addRules(new QueryRule(ObservedValue.FEATURE_NAME, Operator.EQUALS, "TypeOfGroup")); valueQuery.addRules(new QueryRule(ObservedValue.VALUE, Operator.EQUALS, mark)); if (investigationNames.size() > 0) { QueryRule qr1 = new QueryRule(Measurement.INVESTIGATION_NAME, Operator.IN, investigationNames); QueryRule qr2 = new QueryRule(Operator.OR); QueryRule qr3 = new QueryRule(Measurement.INVESTIGATION_NAME, Operator.EQUALS, "System"); valueQuery.addRules(new QueryRule(qr1, qr2, qr3)); // only user's // own OR System // investigations } else { valueQuery.addRules(new QueryRule(Measurement.INVESTIGATION_NAME, Operator.EQUALS, "System")); } valueQuery.addRules(new QueryRule(Operator.SORTASC, ObservedValue.TARGET_NAME)); List<ObservedValue> valueList = valueQuery.find(); for (ObservedValue value : valueList) { panelNameList.add(value.getTarget_Name()); } return getObservationTargets(panelNameList); } /** * Creates an ObservedValue for adding an ObservationTarget to a Panel, but * does NOT add this to the database. However, a protocol application is * created and added to the database, so there is a database transaction * involved, rendering this method unsuitable for use with batch lists. */ public ObservedValue addObservationTargetToPanel(String investigationName, String targetName, Date tmpDate, String panelName) throws DatabaseException, ParseException, IOException { // First, check is target is already in this Panel Query<ObservedValue> q = db.query(ObservedValue.class); q.addRules(new QueryRule(ObservedValue.FEATURE_NAME, Operator.EQUALS, "Group")); q.addRules(new QueryRule(ObservedValue.TARGET_NAME, Operator.EQUALS, targetName)); q.addRules(new QueryRule(ObservedValue.RELATION_NAME, Operator.EQUALS, panelName)); q.addRules(new QueryRule(ObservedValue.ENDTIME, Operator.EQUALS, null)); List<ObservedValue> valueList = q.find(); if (valueList.size() == 0) { ProtocolApplication app = createProtocolApplication(investigationName, "SetGroup"); db.add(app); return createObservedValue(investigationName, app.getName(), tmpDate, null, "Group", targetName, null, panelName); } // Target is already in group, so do not make value return null; } /** * Create a new actor and adds it to the database * * @param investigationId * investigation id * @param actorName * name of actor * @return the id of the new actor * @throws DatabaseException * @throws ParseException * @throws IOException */ @Deprecated public int makeActor(int investigationId, String actorName) throws DatabaseException, ParseException, IOException { ObservationTarget actorToAdd = new ObservationTarget(); actorToAdd.setName(actorName); actorToAdd.setInvestigation_Id(investigationId); // actorToAdd.setOntologyReference_Name(ACTOR); db.add(actorToAdd); return actorToAdd.getId(); } /** * For a given MolgenisUser id, returns the corresponding Actor id. * * @param userId * @return the id of the Actor * @throws DatabaseException * @throws ParseException */ @Deprecated public int getActorId(int userId) throws DatabaseException, ParseException { Query<ObservedValue> q = db.query(ObservedValue.class); q.addRules(new QueryRule(ObservedValue.VALUE, Operator.EQUALS, Integer.toString(userId))); q.addRules(new QueryRule(ObservedValue.FEATURE_NAME, Operator.EQUALS, "MolgenisUserId")); List<ObservedValue> valueList = q.find(); if (valueList.size() > 0) { return valueList.get(0).getTarget_Id(); } else { throw new DatabaseException("No Actor found for MolgenisUser id " + userId); } } /** * Makes a new application of the given protocol but does NOT add it to the * database. Uses Investigation and Protocol Names so it can be used with * lists. */ public ProtocolApplication createProtocolApplication(String investigationName, String protocolName) throws ParseException, DatabaseException, IOException { Date now = new Date(); ProtocolApplication pa = new ProtocolApplication(); pa.setInvestigation_Name(investigationName); pa.setName(protocolName + "_" + protAppCounter++ + "_" + now.toString()); // strange // but // unique // name pa.setProtocol_Name(protocolName); pa.setTime(now); return pa; } /** * Makes a new ProtocolApplication, adds it to the database and return its * name. */ public String makeProtocolApplication(String investigationName, String protocolName) throws DatabaseException, IOException, ParseException { ProtocolApplication pa = createProtocolApplication(investigationName, protocolName); db.add(pa); return pa.getName(); } /** * Find all protocol applications by protocol * * @param protocolid * the id of the protocol to search for * @return A list of matching ProtocolApplications * @throws DatabaseException * @throws ParseException */ public List<ProtocolApplication> getAllProtocolApplicationsByType(String protocolName) throws DatabaseException, ParseException { Query<ProtocolApplication> q = db.query(ProtocolApplication.class); q.addRules(new QueryRule(ProtocolApplication.PROTOCOL_NAME, Operator.EQUALS, protocolName)); return q.find(); } /** * Creates an ObservedValue with the given parameters, but does NOT add it * to the database. Uses investigation, feature, target, protocol * application and relation names to link, so those do not have to have been * added to the DB already. * * @param investigationId * @param protappid * @param starttime * @param endtime * @param featureid * @param subjectTargetId * @param valueString * @param targetRef * @return ObservedValue * @throws DatabaseException * @throws IOException * @throws ParseException */ public ObservedValue createObservedValue(String investigationName, String protappName, Date starttime, Date endtime, String featureName, String subjectTargetName, String valueString, String targetName) throws DatabaseException, IOException, ParseException { ObservedValue newValue = new ObservedValue(); newValue.setInvestigation_Name(investigationName); newValue.setProtocolApplication_Name(protappName); newValue.setFeature_Name(featureName); newValue.setTime(starttime); newValue.setEndtime(endtime); newValue.setTarget_Name(subjectTargetName); if (targetName != null) { newValue.setRelation_Name(targetName); } else { newValue.setValue(valueString); } return newValue; } /** * First makes a ProtocolApplication and adds it to the Database. Then * creates an ObservedValue with the given parameters and a link to the * ProtocolApplication just made, but does NOT add it to the database. * Warning: because this method involves a database transaction, it is not * suited for use with batch lists. */ public ObservedValue createObservedValueWithProtocolApplication(String investigationName, Date starttime, Date endtime, String protocolName, String featureName, String subjectTargetName, String valueString, String targetRefName) throws DatabaseException, IOException, ParseException { // Make and add ProtocolApplication ProtocolApplication app = createProtocolApplication(investigationName, protocolName); db.add(app); ObservedValue newValue = new ObservedValue(); newValue.setInvestigation_Name(investigationName); newValue.setProtocolApplication_Name(app.getName()); newValue.setFeature_Name(featureName); newValue.setTime(starttime); newValue.setEndtime(endtime); newValue.setTarget_Name(subjectTargetName); if (targetRefName != null) { newValue.setRelation_Name(targetRefName); } else { newValue.setValue(valueString); } return newValue; } /** * For a given ObservationTarget and ObservableFeature, returns the value of * the most recent ObservedValue, based on the timestamp of its * ProtocolApplication. Returns null if none found. * * @param targetName * @param featureName * @return String: the most recent value for given feature and target * @throws DatabaseException * @throws ParseException */ public String getMostRecentValueAsString(String targetName, String featureName) throws DatabaseException, ParseException { Query<ObservedValue> q = db.query(ObservedValue.class); q.addRules(new QueryRule(ObservedValue.TARGET_NAME, Operator.EQUALS, targetName)); q.addRules(new QueryRule(ObservedValue.FEATURE_NAME, Operator.EQUALS, featureName)); q.addRules(new QueryRule(Operator.SORTDESC, ObservedValue.TIME)); // Discussion: if you uncomment the next line, only values are retrieved // that have endtime 'null', i.e. values that are still valid. // Is this desirable? Maybe we could use a boolean to switch this // behavior on and off? // q.addRules(new QueryRule(ObservedValue.ENDTIME, Operator.EQUALS, // null)); List<ObservedValue> valueList = q.find(); if (valueList.size() > 0) { ObservedValue returnValue = valueList.get(0); // default is first // one Date storedTime = null; for (ObservedValue currentValue : valueList) { if (currentValue.getProtocolApplication_Id() != null) { String protappName = currentValue.getProtocolApplication_Name(); ProtocolApplication protapp = getProtocolApplicationByName(protappName); Date protappTime = protapp.getTime(); if (storedTime == null || protappTime.after(storedTime)) { returnValue = currentValue; storedTime = protappTime; } } } return returnValue.getValue(); } else { return null; } } /** * For a given ObservationTarget and ObservableFeature, returns the ID of * the ObservationTarget related to in the most recent ObservedValue, based * on the timestamp of its ProtocolApplication. Returns null if none found. */ public String getMostRecentValueAsXrefName(String targetName, String featureName) throws DatabaseException, ParseException { Query<ObservedValue> q = db.query(ObservedValue.class); q.addRules(new QueryRule(ObservedValue.TARGET_NAME, Operator.EQUALS, targetName)); q.addRules(new QueryRule(ObservedValue.FEATURE_NAME, Operator.EQUALS, featureName)); q.addRules(new QueryRule(Operator.SORTDESC, ObservedValue.TIME)); // Discussion: if you uncomment the next line, only values are retrieved // that have endtime 'null', i.e. values that are still valid. // Is this desirable? Maybe we could use a boolean to switch this // behavior on and off? // q.addRules(new QueryRule(ObservedValue.ENDTIME, Operator.EQUALS, // null)); List<ObservedValue> valueList = q.find(); if (valueList.size() > 0) { ObservedValue returnValue = valueList.get(0); // default is first // one Date storedTime = null; for (ObservedValue currentValue : valueList) { if (currentValue.getProtocolApplication_Id() != null) { String protappName = currentValue.getProtocolApplication_Name(); ProtocolApplication protapp = getProtocolApplicationByName(protappName); Date protappTime = protapp.getTime(); if (storedTime == null || protappTime.after(storedTime)) { returnValue = currentValue; storedTime = protappTime; } } } return returnValue.getRelation_Name(); } else { return null; } } /** * Creates a new protocol but does NOT add it to the database. * * @param investigationName * @param protocolName * @param description * @param measurementNameList * @return * @throws DatabaseException * @throws IOException * @throws ParseException */ public Protocol createProtocol(String investigationName, String protocolName, String description, List<String> measurementNameList) throws DatabaseException, IOException, ParseException { Protocol newProtocol = new Protocol(); newProtocol.setName(protocolName); newProtocol.setInvestigation_Name(investigationName); newProtocol.setFeatures_Name(measurementNameList); newProtocol.setDescription(description); return newProtocol; } /** * Finds a protocol id based on protocol name * * @param eventtypeName * @return * @throws DatabaseException * @throws ParseException */ public int getProtocolId(String protocolName) throws DatabaseException, ParseException { Query<Protocol> q = db.query(Protocol.class); q.addRules(new QueryRule(Protocol.NAME, Operator.EQUALS, protocolName)); List<Protocol> protocolList = q.find(); return protocolList.get(0).getId(); } /** * Returns all protocols existing in the database * * @return * @throws DatabaseException * @throws ParseException */ public List<Protocol> getAllProtocols(List<Integer> investigationIds) throws DatabaseException, ParseException { Query<Protocol> q = db.query(Protocol.class); QueryRule qr1 = new QueryRule(Measurement.INVESTIGATION, Operator.IN, investigationIds); QueryRule qr2 = new QueryRule(Operator.OR); QueryRule qr3 = new QueryRule(Measurement.INVESTIGATION_NAME, Operator.EQUALS, "System"); q.addRules(new QueryRule(qr1, qr2, qr3)); // only user's own OR System // investigation return q.find(); } /** * Find a protocol based on protocol name. * */ public Protocol getProtocol(String protocolName) throws DatabaseException, ParseException { Query<Protocol> q = db.query(Protocol.class); q.eq(Protocol.NAME, protocolName); if (q.find() != null) return q.find().get(0); else throw new DatabaseException("No protocol with name " + protocolName + " could be found"); } /** * Get all protocols, sorted on name (ASC or DESC). * * @param sortField * : field to sort on * @param sortOrder * : ASCending or DESCending * @return * @throws DatabaseException * @throws ParseException */ public List<Protocol> getAllProtocolsSorted(String sortField, String sortOrder, List<String> investigationNames) throws DatabaseException, ParseException { Query<Protocol> q = db.query(Protocol.class); QueryRule qr1 = new QueryRule(Measurement.INVESTIGATION_NAME, Operator.IN, investigationNames); QueryRule qr2 = new QueryRule(Operator.OR); QueryRule qr3 = new QueryRule(Measurement.INVESTIGATION_NAME, Operator.EQUALS, "System"); q.addRules(new QueryRule(qr1, qr2, qr3)); // only user's own OR System // investigation if (sortOrder.equals("ASC")) { q.sortASC(sortField); } else { q.sortDESC(sortField); } return q.find(); } /** * Create a new ontologyterm and add it to the database, returning the id * * @param name * @param ontologyId * @param description * @return new ontologyterm id * @throws DatabaseException * @throws IOException * @throws ParseException */ public int makeOntologyTerm(String name, int ontologyId, String description) throws DatabaseException, IOException, ParseException { OntologyTerm newOnt = new OntologyTerm(); newOnt.setName(name); newOnt.setOntology(ontologyId); newOnt.setDefinition(description); db.add(newOnt); return newOnt.getId(); } /** * Gets the ID of the measurement with the name "measurementName" * * @param measurementName * @return int ID * @throws DatabaseException * @throws ParseException */ public int getMeasurementId(String measurementName) throws DatabaseException, ParseException { Query<Measurement> q = db.query(Measurement.class); q.eq(Measurement.NAME, measurementName); List<Measurement> featList = q.find(); if (featList.size() > 0) return featList.get(0).getId(); else throw new DatabaseException("Id could be found for" + " Measurement with name: " + measurementName); } /** * Return a list of all measurements in the database * * @return * @throws DatabaseException * @throws ParseException */ public List<Measurement> getAllMeasurements(List<String> investigationNames) throws DatabaseException, ParseException { Query<Measurement> q = db.query(Measurement.class); q.sortASC(Measurement.ID); if (investigationNames.size() > 0) { QueryRule qr1 = new QueryRule(Measurement.INVESTIGATION_NAME, Operator.IN, investigationNames); QueryRule qr2 = new QueryRule(Operator.OR); QueryRule qr3 = new QueryRule(Measurement.INVESTIGATION_NAME, Operator.EQUALS, "System"); q.addRules(new QueryRule(qr1, qr2, qr3)); // only user's own OR // System investigation } else { q.addRules(new QueryRule(Measurement.INVESTIGATION_NAME, Operator.EQUALS, "System")); } return q.find(); } /** * Get all Measurement, sorted on name (ASC or DESC). * * @param sortField * : field to sort on * @param sortOrder * : ASCending or DESCending * @return A list of all ObservableFeatures sorted by argument * @throws DatabaseException * @throws ParseException */ public List<Measurement> getAllMeasurementsSorted(String sortField, String sortOrder, List<String> investigationNames) throws DatabaseException, ParseException { Query<Measurement> q = db.query(Measurement.class); if (sortOrder.equals("ASC")) { q.sortASC(sortField); } else { q.sortDESC(sortField); } if (investigationNames.size() > 0) { QueryRule qr1 = new QueryRule(Measurement.INVESTIGATION_NAME, Operator.IN, investigationNames); QueryRule qr2 = new QueryRule(Operator.OR); QueryRule qr3 = new QueryRule(Measurement.INVESTIGATION_NAME, Operator.EQUALS, "System"); q.addRules(new QueryRule(qr1, qr2, qr3)); // only user's own OR // System investigation } else { q.addRules(new QueryRule(Measurement.INVESTIGATION_NAME, Operator.EQUALS, "System")); } return q.find(); } /** * Returns a list of all existing ObservableFeatures. * * @return * @throws DatabaseException * @throws ParseException */ public List<ObservableFeature> getAllObservableFeatures(List<String> investigationNames) throws DatabaseException, ParseException { Query<ObservableFeature> q = db.query(ObservableFeature.class); q.sortASC(ObservableFeature.ID); if (investigationNames.size() > 0) { QueryRule qr1 = new QueryRule(Measurement.INVESTIGATION_NAME, Operator.IN, investigationNames); QueryRule qr2 = new QueryRule(Operator.OR); QueryRule qr3 = new QueryRule(Measurement.INVESTIGATION_NAME, Operator.EQUALS, "System"); q.addRules(new QueryRule(qr1, qr2, qr3)); // only user's own OR // System investigation } else { q.addRules(new QueryRule(Measurement.INVESTIGATION_NAME, Operator.EQUALS, "System")); } return q.find(); } /** * Returns a list of all Measurements for a Protocol * * @param protocolId * @return * @throws DatabaseException * @throws ParseException */ public List<Measurement> getMeasurementsByProtocol(String protocolName) throws DatabaseException, ParseException { Protocol protocol = db.query(Protocol.class).eq(Protocol.NAME, protocolName).find().get(0); List<Measurement> features = new ArrayList<Measurement>(); for (Integer i : protocol.getFeatures_Id()) { features.add(db.findById(Measurement.class, i)); } return features; } /** * Finds a Measurement entity by its name * * @param featureId * @return * @throws DatabaseException * @throws ParseException */ public Measurement getMeasurementByName(String featureName) throws DatabaseException, ParseException { return db.find(Measurement.class, new QueryRule(Measurement.NAME, Operator.EQUALS, featureName)).get(0); } /** * Create and add a Measurement to the database. Note: unlike the other * makeMeasurement(), this method does NOT set the Investigation, the Unit, * the TargettypeAllowedForRelation, the panelLabelAllowedForRelation and * the Temporal fields. * * @param name * observablefeature name * @param description * observablefeature description * @param dataType * the data type of the observablefeature * @throws IOException * @throws DatabaseException */ @Deprecated public void makeMeasurement(String name, String description, String dataType) throws DatabaseException, IOException { Measurement feature = new Measurement(); feature.setName(name); feature.setDataType(dataType); feature.setDescription(description); db.add(feature); } /** * Creates a new Measurement and adds it to the databases * * @param investigationId * @param name * @param unitId * @param targettypeAllowedForRelation * @param panelLabelAllowedForRelation * @param focal * @param dataType * @param description * @return * @throws DatabaseException * @throws IOException * @throws ParseException */ public int makeMeasurement(String investigationName, String name, String unitName, String targettypeAllowedForRelationClassName, String panelLabelAllowedForRelation, boolean temporal, String dataType, String description, String userName) throws DatabaseException, IOException, ParseException { Measurement newFeat = createMeasurement(investigationName, name, unitName, targettypeAllowedForRelationClassName, panelLabelAllowedForRelation, temporal, dataType, description, userName); db.add(newFeat); return newFeat.getId(); } /** * Creates a new Measurement but does NOT add it to the database. * * @param investigationName * @param name * @param unitName * @param targettypeAllowedForRelationName * @param panelLabelAllowedForRelation * @param temporal * @param dataType * @param description * @param userName * @return * @throws DatabaseException * @throws IOException * @throws ParseException */ public Measurement createMeasurement(String investigationName, String name, String unitName, String targettypeAllowedForRelationClassName, String panelLabelAllowedForRelation, boolean temporal, String dataType, String description, String userName) throws DatabaseException, IOException, ParseException { Measurement newFeat = new Measurement(); newFeat.setName(name); newFeat.setInvestigation_Name(investigationName); newFeat.setUnit_Name(unitName); if (targettypeAllowedForRelationClassName != null) { newFeat.setTargettypeAllowedForRelation_ClassName(targettypeAllowedForRelationClassName); } if (panelLabelAllowedForRelation != null) { newFeat.setPanelLabelAllowedForRelation(panelLabelAllowedForRelation); } newFeat.setTemporal(temporal); newFeat.setDataType(dataType); newFeat.setDescription(description); newFeat.setOwns_Name(userName); return newFeat; } /** * Creates a new entry in the Category table and updates the Measurement for * which it is a Category. * * @param code * : the code itself * @param desc * : the description of what the code stands for * @param feat * : the name of the ObservableFeature this Code can be used for * @throws DatabaseException * @throws ParseException * @throws IOException */ public void makeCategory(String code, String desc, String feat) throws DatabaseException, ParseException, IOException { Category newCode = new Category(); newCode.setName(feat + "_" + code); newCode.setCode_String(code); newCode.setLabel(code); newCode.setDescription(desc); db.add(newCode); // now add it to the Measurement Measurement m = db.query(Measurement.class).eq(Measurement.NAME, feat).find().get(0); m.getCategories_Id().add(newCode.getId()); db.update(m); } /** * Creates a new Category table but does NOT add it to the database and does * NOT update the Measurement for which it is a Category. * * @param code * : the code itself * @param desc * : the description of what the code stands for * @throws DatabaseException * @throws ParseException * @throws IOException */ public Category createCategory(String code, String desc, String feat) throws DatabaseException, ParseException, IOException { Category newCode = new Category(); newCode.setName(feat + "_" + code); newCode.setCode_String(code); newCode.setLabel(code); newCode.setDescription(desc); return newCode; } /** * Finds all Code entities for a given feature name and returns their * descriptions. * * @param featurename * @return * @throws DatabaseException * @throws ParseException */ public List<String> getAllCodesForFeatureAsStrings(String featurename) throws DatabaseException, ParseException { Measurement m = db.query(Measurement.class).eq(Measurement.NAME, featurename).find().get(0); List<Category> tmpList = db.query(Category.class).in(Category.ID, m.getCategories_Id()).find(); // int featureid = getMeasurementId(featurename); // Query<Category> q = db.query(Category.class); // q.eq(Category.FEATURE, featureid); List<String> returnList = new ArrayList<String>(); // List<Category> tmpList = q.find(); for (Category code : tmpList) { returnList.add(code.getDescription()); } return returnList; } /** * Finds all code entities for a given feature name * * @param featureName * @return * @throws DatabaseException * @throws ParseException */ public List<Category> getAllCodesForFeature(String featureName) throws DatabaseException, ParseException { Measurement m = db.query(Measurement.class).eq(Measurement.NAME, featureName).find().get(0); return db.query(Category.class).in(Category.ID, m.getCategories_Id()).find(); } /** * Add one or more ObservationTargets to the database. * * @param targets * : the observation targets to be added * @throws DatabaseException * @throws IOException */ public void addObservationTargets(List<ObservationTarget> targets) throws DatabaseException, IOException { for (ObservationTarget o : targets) { db.add(o); } } /** * Add a protocol to the database * * @param name * protocol name * @param description * protocol description * @throws IOException * @throws DatabaseException * @throws ParseException */ public void addProtocol(String name, String description, List<String> observableFeatureNames) throws DatabaseException, IOException, ParseException { Protocol protocol = new Protocol(); protocol.setName(name); protocol.setDescription(description); List<Integer> featureIds = new ArrayList<Integer>(); for (String s : observableFeatureNames) { // TODO: This query is inefficient - returns a bunch of objects when // only IDs are needed // How can only IDs be returned in this query system? Query<ObservableFeature> q = db.query(ObservableFeature.class); q.eq(ObservableFeature.NAME, s); if (!q.find().isEmpty()) { featureIds.add(q.find().get(0).getId()); } else { // this should not happen logger.error("Name could not be found and feature:" + s + " will not be added to the protocol"); } } protocol.setFeatures_Id(featureIds); db.add(protocol); } /** * Returns all observed values for a given ObservationTarget and * measurement, sorted so that the most recent one comes first. * * @param targetname * The name of the target * @param measurementname * The name of the measurement * @param investigation * list A list of investigations of which the target can be part * of. * @throws IOException * @throws DatabaseException * @return a list of observed values. * */ public List<ObservedValue> getObservedValuesByTargetAndMeasurement(String targetName, String mName, List<Integer> investigationIds) throws DatabaseException, ParseException { List<ObservedValue> obsVal = new ArrayList<ObservedValue>(); Query<ObservedValue> q = db.query(ObservedValue.class); q.addRules(new QueryRule(ObservedValue.TARGET_NAME, Operator.EQUALS, targetName)); q.addRules(new QueryRule(ObservedValue.FEATURE_NAME, Operator.EQUALS, mName)); q.addRules(new QueryRule(ObservedValue.INVESTIGATION, Operator.IN, investigationIds)); q.addRules(new QueryRule(Operator.SORTDESC, ObservedValue.TIME)); List<ObservedValue> vals = q.find(); if (vals.isEmpty()) { return null; } else { obsVal.addAll(vals); return obsVal; } } /** * Returns all observed values for a given ObservationTarget and list of * features, sorted so that the most recent one comes first. NOTE: Creates a * default "" value if observedValue doesn't exist yet for given feature and * sample. This created default does not link to a ProtocolApplication and * this method isn't responsible for storing this object in the database. */ public List<ObservedValue> getObservedValuesByTargetAndFeatures(String targetName, List<String> measurementNames, List<String> investigationNames, String investigationToAddToName) throws DatabaseException, ParseException { List<ObservedValue> values = new ArrayList<ObservedValue>(); for (String mName : measurementNames) { // for each feature, find/make value(s) Query<ObservedValue> q = db.query(ObservedValue.class); q.addRules(new QueryRule(ObservedValue.TARGET_NAME, Operator.EQUALS, targetName)); q.addRules(new QueryRule(ObservedValue.FEATURE_NAME, Operator.EQUALS, mName)); q.addRules(new QueryRule(ObservedValue.INVESTIGATION_NAME, Operator.IN, investigationNames)); q.addRules(new QueryRule(Operator.SORTDESC, ObservedValue.TIME)); List<ObservedValue> vals = q.find(); // FIXME Why the heck does this "get"function add an empty value to // the DB ? //ate 2012-06-14 if (vals.isEmpty()) { // if value doesn't exist, create new one ObservedValue newOV = new ObservedValue(); newOV.setFeature_Name(mName); newOV.setValue(""); // don't set relation, as that can then never be reset to null newOV.setTarget_Name(targetName); newOV.setInvestigation_Name(investigationToAddToName); values.add(newOV); } else { values.addAll(vals); } } return values; } /** * Returns all observed values for a given ObservationTarget and * ObservableFeature, sorted so that the most recent one comes first. NOTE: * Creates a default "" value if observedValue doesn't exist yet for given * feature and sample. This created default does not link to a * ProtocolApplication and this method isn't responsible for storing this * object in the database. */ public List<ObservedValue> getObservedValuesByTargetAndFeature(String targetName, String measurementName, List<String> investigationNames, String investigationToBeAddedToName) throws DatabaseException, ParseException { List<String> measurementNameList = new ArrayList<String>(); measurementNameList.add(measurementName); return getObservedValuesByTargetAndFeatures(targetName, measurementNameList, investigationNames, investigationToBeAddedToName); } /** * Finds a protocolapplication entity by its name * * @param name * @return * @throws DatabaseException * @throws ParseException */ public ProtocolApplication getProtocolApplicationByName(String name) throws DatabaseException, ParseException { Query<ProtocolApplication> q = db.query(ProtocolApplication.class); q.addRules(new QueryRule(ProtocolApplication.NAME, Operator.EQUALS, name)); if (!q.find().isEmpty()) { return q.find().get(0); } else throw new DatabaseException("No protocolapplication with name " + name + "could be found."); } /** * Get Investigation based on name * * @param name * @return * @throws DatabaseException * @throws ParseException */ public Investigation getInvestigation(String name) throws DatabaseException, ParseException { Query<Investigation> s = db.query(Investigation.class); s.addRules(new QueryRule(Investigation.NAME, Operator.EQUALS, name)); if (s.find().isEmpty()) { throw new DatabaseException("Investigation with name " + name + " does not exist."); } else return s.find().get(0); } /** * Get the name of the given MolgenisEntity. Returns null if it doesn't * exist. * * @param entityId * @return */ public String getEntityName(int entityId) { try { return db.findById(MolgenisEntity.class, entityId).getName(); } catch (DatabaseException e) { return null; } } /** * Returns the id of the ObservableFeature the user has chosen as custom * name for the ObservationTargets, or -1 if none was set. * * @param userId * @return */ public int getCustomNameFeatureId(String userName) { if (userName == null) { return -1; } try { int userId = db.query(MolgenisUser.class).eq(MolgenisUser.NAME, userName).find().get(0).getId(); return db.query(CustomLabelFeature.class).eq(CustomLabelFeature.USERID, userId).find().get(0) .getFeatureId_Id(); } catch (Exception e) { return -1; } } /** * Makes a map of all ObservationTarget id's and names. The names are * retrieved using the feature name specified, or -if no feature is * specified- the normal database name is taken. To improve performance, * does not make a map if one already exists. */ public void makeObservationTargetNameMap(String userName, boolean force) { if (observationTargetNameMap != null && force == false) { return; } observationTargetNameMap = new HashMap<Integer, String>(); List<String> invNameList = getAllUserInvestigationNames(userName); // First fill with standard names for all the investigations the current // user has rights on List<ObservationTarget> targetList = new ArrayList<ObservationTarget>(); try { targetList = getAllObservationTargets(invNameList); } catch (Exception e) { // targetList will remain empty return; } for (ObservationTarget target : targetList) { try { observationTargetNameMap.put(target.getId(), target.getName()); } catch (Exception e) { // no name found, so put ID as name observationTargetNameMap.put(target.getId(), target.getId().toString()); } } // Then overwrite with custom names, if existing int customNameFeatureId = getCustomNameFeatureId(userName); if (customNameFeatureId != -1) { try { Query<ObservedValue> valueQuery = db.query(ObservedValue.class); valueQuery.addRules(new QueryRule(ObservedValue.FEATURE, Operator.EQUALS, customNameFeatureId)); valueQuery.addRules(new QueryRule(ObservedValue.TARGET_NAME, Operator.IN, getAllObservationTargetNames( null, false, invNameList))); List<ObservedValue> valueList = valueQuery.find(); for (ObservedValue value : valueList) { if (value.getValue() != null) { // We have a String value that we can use observationTargetNameMap.put(value.getTarget_Id(), value.getValue()); } else { // No value, so use relation observationTargetNameMap.put(value.getTarget_Id(), value.getRelation_Name()); } } } catch (Exception e) { // No fancy names then... } } } /** * Get all the prefixes (non-numeric parts) of the ObservationTarget names * that are in the DB. Example: say there are ObservationTargets with names * Morris1, Morris2 and Jessica99. This method will then return [Morris, * Jessica]. * * @return */ public List<String> getPrefixes(String targetType) throws DatabaseException { List<String> returnList = new ArrayList<String>(); List<NamePrefix> prefixList = db.find(NamePrefix.class); if (prefixList != null && prefixList.size() > 0) { for (NamePrefix prefix : prefixList) { if (prefix.getTargetType().equals(targetType)) { returnList.add(prefix.getPrefix()); } } } return returnList; // List<ObservationTarget> allTargetList = // db.find(ObservationTarget.class); // for (ObservationTarget target : allTargetList) { // String name = target.getName(); // name = name.replaceAll("\\d+$", ""); // if (!name.equals("") && !returnList.contains(name)) { // returnList.add(name); // } // } } /** * Get the highest number found in the DB following the given * ObservationTarget name base. Example: say there are ObservationTargets * with names Morris1, Morris2 and Jessica99. This method, when passed * 'Morris', will return 2. * * @param base * @return * @throws DatabaseException */ public int getHighestNumberForPrefix(String prefix) throws DatabaseException { List<NamePrefix> prefixList = db.find(NamePrefix.class, new QueryRule(NamePrefix.PREFIX, Operator.EQUALS, prefix)); if (prefixList != null && prefixList.size() > 0) { return prefixList.get(0).getHighestNumber(); } return 0; // int maxTrailingNumber = 0; // List<ObservationTarget> targetList = db.find(ObservationTarget.class, // new QueryRule(ObservationTarget.NAME, Operator.LIKE, base)); // for (ObservationTarget target : targetList) { // String name = target.getName(); // // Extra check on name // if (!name.startsWith(base)) { // continue; // } // Pattern p; // if (base.equals("")) { // // With an empty base, name may consist of numbers only // p = Pattern.compile("^\\d+$"); // } else { // p = Pattern.compile("\\d+$"); // } // Matcher m = p.matcher(name); // if (!m.find()) { // continue; // } // int trailingNumber = Integer.parseInt(m.group()); // if (trailingNumber > maxTrailingNumber) { // maxTrailingNumber = trailingNumber; // } // } // return maxTrailingNumber; } public void updatePrefix(String targetType, String prefix, int highestNr) throws DatabaseException { List<NamePrefix> prefixList = db.find(NamePrefix.class, new QueryRule(NamePrefix.PREFIX, Operator.EQUALS, prefix)); if (prefixList != null && prefixList.size() > 0) { // Update NamePrefix namePrefix = prefixList.get(0); namePrefix.setHighestNumber(highestNr); db.update(namePrefix); } else { // New NamePrefix namePrefix = new NamePrefix(); namePrefix.setTargetType(targetType); namePrefix.setPrefix(prefix); namePrefix.setHighestNumber(highestNr); db.add(namePrefix); } } public String prependZeros(String name, int totalNrOfChars) { char[] nameChars = name.toCharArray(); if (nameChars.length >= totalNrOfChars) { return name; } char[] fullNameChars = new char[totalNrOfChars]; int i = 0; for (; i < totalNrOfChars - nameChars.length; i++) { fullNameChars[i] = '0'; } for (; i < totalNrOfChars; i++) { fullNameChars[i] = nameChars[i - (totalNrOfChars - nameChars.length)]; } return String.valueOf(fullNameChars); } /** * Get a list of all the remarks that have been set on the target with name * 'targetName'. * * @param targetId * @return * @throws DatabaseException */ public List<String> getRemarks(String targetName) throws DatabaseException { Query<ObservedValue> q = db.query(ObservedValue.class); q.addRules(new QueryRule(ObservedValue.FEATURE_NAME, Operator.EQUALS, "Remark")); q.addRules(new QueryRule(ObservedValue.TARGET_NAME, Operator.EQUALS, targetName)); List<ObservedValue> valueList = q.find(); List<String> returnList = new ArrayList<String>(); if (valueList != null && valueList.size() > 0) { for (ObservedValue value : valueList) { returnList.add(value.getValue()); } } return returnList; } }