예제 #1
0
 private void setRefsAndCollections(List<String> parents, Item feature) {
   String clsName = feature.getClassName();
   Map<String, String> refsAndCollections = handler.getRefsAndCollections();
   if (refsAndCollections != null
       && refsAndCollections.containsKey(clsName)
       && parents != null
       && !parents.isEmpty()) {
     ClassDescriptor cld =
         tgtModel.getClassDescriptorByName(tgtModel.getPackageName() + "." + clsName);
     String refName = refsAndCollections.get(clsName);
     Iterator<String> parentIter = parents.iterator();
     if (cld.getReferenceDescriptorByName(refName, true) != null) {
       String parent = parentIter.next();
       feature.setReference(refName, getRefId(parent));
       if (parentIter.hasNext()) {
         String primaryIdent = feature.getAttribute("primaryIdentifier").getValue();
         throw new RuntimeException(
             "Feature has multiple relations for reference: "
                 + refName
                 + " for feature: "
                 + feature.getClassName()
                 + ", "
                 + feature.getIdentifier()
                 + ", "
                 + primaryIdent);
       }
     } else if (cld.getCollectionDescriptorByName(refName, true) != null) {
       List<String> refIds = new ArrayList<String>();
       while (parentIter.hasNext()) {
         refIds.add(getRefId(parentIter.next()));
       }
       feature.setCollection(refName, refIds);
     } else if (parentIter.hasNext()) {
       throw new RuntimeException(
           "No '"
               + refName
               + "' reference/collection found in "
               + "class: "
               + clsName
               + " - is map configured correctly?");
     }
   }
 }
  /**
   * Search for the classes in a collection for a given InterMineObject, for example find all of the
   * sub-classes of Employee in the Department.employees collection of a given Department. If there
   * are no subclasses or the collection is empty a list with the type of the collection is
   * returned.
   *
   * @param object an InterMineObject to inspect
   * @param field the name if the collection to check
   * @param os the ObjectStore in which to execute the query
   * @return a list of classes in the collection
   */
  public static List<Class<?>> queryForTypesInCollection(
      InterMineObject object, String field, ObjectStore os) {
    List<Class<?>> typesInCollection = new ArrayList<Class<?>>();

    // if there are no subclasses there can only be one type in the collection
    Model model = os.getModel();
    ClassDescriptor startCld =
        model.getClassDescriptorByName(DynamicUtil.getSimpleClassName(object));
    CollectionDescriptor col = startCld.getCollectionDescriptorByName(field, true);
    ClassDescriptor colCld = col.getReferencedClassDescriptor();

    if (model.getAllSubs(colCld).isEmpty()) {
      // there aren't any subclasses, so no need to do a query
      typesInCollection.add(colCld.getType());
    } else {
      // there may be multiple subclasses in the collection, need to run a query
      Query query = new Query();
      QueryClass qc = new QueryClass(colCld.getType());
      query.addFrom(qc);
      query.addToSelect(new QueryField(qc, "class"));
      query.setDistinct(true);
      query.setConstraint(
          new ContainsConstraint(
              new QueryCollectionReference(object, field), ConstraintOp.CONTAINS, qc));
      for (Object o : os.executeSingleton(query)) {
        typesInCollection.add((Class<?>) o);
      }

      // Collection was empty but add collection type to be consistent with collection types
      // without subclasses.
      if (typesInCollection.isEmpty()) {
        typesInCollection.add(colCld.getType());
      }
    }
    return typesInCollection;
  }
예제 #3
0
  /**
   * Add a collection of objects of type X to objects of type Y by using a connecting class. Eg. Add
   * a collection of Protein objects to Gene by examining the Transcript objects in the transcripts
   * collection of the Gene, which would use a query like: SELECT DISTINCT gene FROM Gene AS gene,
   * Transcript AS transcript, Protein AS protein WHERE (gene.transcripts CONTAINS transcript AND
   * transcript.protein CONTAINS protein) ORDER BY gene and then set protected gene.protein (if
   * created BioEntity1 -&gt; BioEntity2 -&gt; BioEntity3 ==&gt; BioEntity1 -&gt; BioEntity3
   *
   * @param firstClsName the first class in the query
   * @param firstClassFieldName the field in the firstClass which should contain the connectingClass
   * @param connectingClsName the class referred to by firstClass.sourceFieldName
   * @param connectingClassFieldName the field in connectingClass which should contain secondClass
   * @param secondClsName the class referred to by connectingClass.connectingClassFieldName
   * @param createFieldName the collection field in the secondClass - the collection to create/set
   * @param createInFirstClass if true create the new collection field in firstClass, otherwise
   *     create in secondClass
   * @throws Exception if anything goes wrong
   */
  protected void insertCollectionField(
      String firstClsName,
      String firstClassFieldName,
      String connectingClsName,
      String connectingClassFieldName,
      String secondClsName,
      String createFieldName,
      boolean createInFirstClass)
      throws Exception {
    InterMineObject lastDestObject = null;
    Set<InterMineObject> newCollection = new HashSet<InterMineObject>();

    String insertMessage =
        "insertCollectionField("
            + firstClsName
            + ", "
            + firstClassFieldName
            + ", "
            + connectingClsName
            + ", "
            + connectingClassFieldName
            + ","
            + secondClsName
            + ", "
            + createFieldName
            + ", "
            + createInFirstClass
            + ")";

    // Check that classes and fields specified exist in model
    try {
      String errorMessage = "Not performing " + insertMessage;
      PostProcessUtil.checkFieldExists(model, firstClsName, firstClassFieldName, errorMessage);
      PostProcessUtil.checkFieldExists(
          model, connectingClsName, connectingClassFieldName, errorMessage);
      PostProcessUtil.checkFieldExists(model, secondClsName, createFieldName, errorMessage);
    } catch (MetaDataException e) {
      return;
    }

    LOG.info("Beginning " + insertMessage);
    long startTime = System.currentTimeMillis();

    // if this is a many to many collection we can use ObjectStore.addToCollection which will
    // write directly to the database.
    boolean manyToMany = false;
    ClassDescriptor destCld;
    if (createInFirstClass) {
      destCld = model.getClassDescriptorByName(firstClsName);
    } else {
      destCld = model.getClassDescriptorByName(secondClsName);
    }
    CollectionDescriptor col = destCld.getCollectionDescriptorByName(createFieldName);
    if (col == null) {
      String msg =
          "Error running post-process `create-references` for `"
              + createFieldName
              + "` since this collection doesn't exist in the model.";
      LOG.error(msg);
      return;
    }

    if (col.relationType() == CollectionDescriptor.M_N_RELATION) {
      manyToMany = true;
    }

    Iterator<ResultsRow<InterMineObject>> resIter =
        PostProcessUtil.findConnectingClasses(
            osw.getObjectStore(),
            model.getClassDescriptorByName(firstClsName).getType(),
            firstClassFieldName,
            model.getClassDescriptorByName(connectingClsName).getType(),
            connectingClassFieldName,
            model.getClassDescriptorByName(secondClsName).getType(),
            createInFirstClass);

    // results will be firstClass ; destClass (ordered by firstClass)
    osw.beginTransaction();
    int count = 0;

    while (resIter.hasNext()) {
      ResultsRow<InterMineObject> rr = resIter.next();

      InterMineObject thisSourceObject;
      InterMineObject thisDestObject;

      if (createInFirstClass) {
        thisDestObject = rr.get(0);
        thisSourceObject = rr.get(1);
      } else {
        thisDestObject = rr.get(1);
        thisSourceObject = rr.get(0);
      }

      if (!manyToMany
          && (lastDestObject == null || !thisDestObject.getId().equals(lastDestObject.getId()))) {

        if (lastDestObject != null) {
          try {
            InterMineObject tempObject = PostProcessUtil.cloneInterMineObject(lastDestObject);
            Set<InterMineObject> oldCollection =
                (Set<InterMineObject>) tempObject.getFieldValue(createFieldName);
            newCollection.addAll(oldCollection);
            tempObject.setFieldValue(createFieldName, newCollection);
            count += newCollection.size();
            osw.store(tempObject);
          } catch (IllegalAccessException e) {
            LOG.error(
                "Object with ID "
                    + thisDestObject.getId()
                    + " has no "
                    + createFieldName
                    + " field",
                e);
          }
        }

        newCollection = new HashSet<InterMineObject>();
      }

      if (manyToMany) {
        osw.addToCollection(
            thisDestObject.getId(), destCld.getType(), createFieldName, thisSourceObject.getId());
      } else {
        newCollection.add(thisSourceObject);
      }

      lastDestObject = thisDestObject;
    }

    if (!manyToMany && lastDestObject != null) {
      // clone so we don't change the ObjectStore cache
      InterMineObject tempObject = PostProcessUtil.cloneInterMineObject(lastDestObject);
      tempObject.setFieldValue(createFieldName, newCollection);
      count += newCollection.size();
      osw.store(tempObject);
    }
    LOG.info(
        "Finished: created "
            + count
            + " references in "
            + secondClsName
            + " to "
            + firstClsName
            + " via "
            + connectingClsName
            + " - took "
            + (System.currentTimeMillis() - startTime)
            + " ms.");
    osw.commitTransaction();

    // now ANALYSE tables relation to class that has been altered - may be rows added
    // to indirection tables
    if (osw instanceof ObjectStoreWriterInterMineImpl) {
      ClassDescriptor cld = model.getClassDescriptorByName(secondClsName);
      DatabaseUtil.analyse(((ObjectStoreWriterInterMineImpl) osw).getDatabase(), cld, false);
    }
  }