@Override
  public UpdateContainer doIt(VWorkspace vWorkspace) throws CommandException {
    Worksheet worksheet = vWorkspace.getViewFactory().getVWorksheet(vWorksheetId).getWorksheet();

    Workspace ws = vWorkspace.getWorkspace();
    if (worksheet.getSemanticTypes().getListOfTypes().size() == 0) {
      SemanticTypeUtil.populateSemanticTypesUsingCRF(
          worksheet,
          ws.getTagsContainer().getTag(TagName.Outlier),
          ws.getCrfModelHandler(),
          ws.getOntologyManager());
    }

    WorksheetGeospatialContent geo = new WorksheetGeospatialContent(worksheet);
    // Send an error update if no geospatial data found!
    if (geo.hasNoGeospatialData()) {
      return new UpdateContainer(new ErrorUpdate("No geospatial data found in the worksheet!"));
    }

    try {
      final File file = geo.publishKML();
      // Transfer the file to a public server
      final boolean transfer = transferFileToPublicServer(file);
      if (!transfer) {
        logger.error(
            "Published KML file could not be moved to a public server to display on Google Maps!");
      }

      return new UpdateContainer(
          new AbstractUpdate() {
            @Override
            public void generateJson(String prefix, PrintWriter pw, VWorkspace vWorkspace) {
              JSONObject outputObject = new JSONObject();
              try {
                outputObject.put(JsonKeys.updateType.name(), "PublishKMLUpdate");
                outputObject.put(JsonKeys.fileName.name(), publicKMLAddress + file.getName());
                outputObject.put(JsonKeys.transferSuccessful.name(), transfer);
                outputObject.put(JsonKeys.localFileName.name(), "KML/" + file.getName());
                pw.println(outputObject.toString(4));
              } catch (JSONException e) {
                logger.error("Error occured while generating JSON!");
              }
            }
          });
    } catch (FileNotFoundException e) {
      logger.error("KML File not found!", e);
      return new UpdateContainer(new ErrorUpdate("Error occurred while publishing KML layer!"));
    }
  }
  @Override
  public UpdateContainer doIt(VWorkspace vWorkspace) throws CommandException {
    UpdateContainer c = new UpdateContainer();
    Worksheet worksheet = vWorkspace.getViewFactory().getVWorksheet(vWorksheetId).getWorksheet();

    worksheetName = worksheet.getTitle();

    // Generate the semantic types for the worksheet
    OntologyManager ontMgr = vWorkspace.getWorkspace().getOntologyManager();
    if (ontMgr.isEmpty()) return new UpdateContainer(new ErrorUpdate("No ontology loaded."));

    SemanticTypeUtil.computeSemanticTypesForAutoModel(
        worksheet, vWorkspace.getWorkspace().getCrfModelHandler(), ontMgr);

    String alignmentId =
        AlignmentManager.Instance()
            .constructAlignmentId(vWorkspace.getWorkspace().getId(), vWorksheetId);
    Alignment alignment = AlignmentManager.Instance().getAlignment(alignmentId);
    if (alignment == null) {
      alignment = new Alignment(ontMgr);
      AlignmentManager.Instance().addAlignmentToMap(alignmentId, alignment);
    }
    try {
      // Save the semantic types in the input parameter JSON
      saveSemanticTypesInformation(
          worksheet, vWorkspace, worksheet.getSemanticTypes().getListOfTypes());

      // Add the visualization update
      c.add(new SemanticTypesUpdate(worksheet, vWorksheetId, alignment));
      c.add(
          new SVGAlignmentUpdate_ForceKarmaLayout(
              vWorkspace.getViewFactory().getVWorksheet(vWorksheetId), alignment));
    } catch (Exception e) {
      logger.error("Error occured while generating the model Reason:.", e);
      return new UpdateContainer(
          new ErrorUpdate("Error occured while generating the model for the source."));
    }
    c.add(new TagsUpdate());
    return c;
  }
  @Override
  public void generateJson(String prefix, PrintWriter pw, VWorkspace vWorkspace) {
    Workspace workspace = vWorkspace.getWorkspace();
    alignment = AlignmentManager.Instance().getAlignment(workspace.getId(), worksheetId);
    SemanticTypes types = worksheet.getSemanticTypes();
    Map<String, ColumnNode> hNodeIdTocolumnNodeMap = createColumnNodeMap();
    Map<String, SemanticTypeNode> hNodeIdToDomainNodeMap = createDomainNodeMap();

    JSONStringer jsonStr = new JSONStringer();
    try {
      JSONWriter writer = jsonStr.object();
      writer.key("worksheetId").value(worksheetId).key("updateType").value("SemanticTypesUpdate");

      writer.key(JsonKeys.Types.name());
      writer.array();
      // Iterate through all the columns
      for (HNodePath path : worksheet.getHeaders().getAllPaths()) {
        HNode node = path.getLeaf();
        String nodeId = node.getId();

        writer.object();

        // Check if a semantic type exists for the HNode
        SemanticType type = types.getSemanticTypeForHNodeId(nodeId);
        if (type != null && type.getConfidenceLevel() != SemanticType.ConfidenceLevel.Low) {
          writer
              .key(JsonKeys.HNodeId.name())
              .value(type.getHNodeId())
              .key(JsonKeys.SemanticTypesArray.name())
              .array();

          ColumnNode alignmentColumnNode = hNodeIdTocolumnNodeMap.get(type.getHNodeId());
          SemanticTypeNode domainNode = hNodeIdToDomainNodeMap.get(type.getHNodeId());

          if (alignmentColumnNode == null || domainNode == null) {
            logger.error(
                "Column node or domain node not found in alignment."
                    + " (This should not happen conceptually!):"
                    + type);
            continue;
          }

          // Add the primary semantic type
          writer
              .object()
              .key(JsonKeys.Origin.name())
              .value(type.getOrigin().name())
              .key(JsonKeys.ConfidenceLevel.name())
              .value(type.getConfidenceLevel().name())
              .key(JsonKeys.isPrimary.name())
              .value(true);

          // Add the RDF literal type to show in the text box
          String rdfLiteralType =
              alignmentColumnNode.getRdfLiteralType() == null
                  ? ""
                  : alignmentColumnNode.getRdfLiteralType().getDisplayName();
          String language =
              alignmentColumnNode.getLanguage() == null ? "" : alignmentColumnNode.getLanguage();
          writer.key(JsonKeys.rdfLiteralType.name()).value(rdfLiteralType);
          writer.key(JsonKeys.language.name()).value(language);

          //					String domainDisplayLabel = (domainNode.getLabel().getPrefix() != null &&
          // (!domainNode.getLabel().getPrefix().equals(""))) ?
          //							(domainNode.getLabel().getPrefix() + ":" + domainNode.getLocalId()) :
          // domainNode.getLocalId();
          if (!type.isClass()) {
            writer
                .key(JsonKeys.FullType.name())
                .value(type.getType().getUri())
                .key(JsonKeys.DisplayLabel.name())
                .value(type.getType().getDisplayName())
                .key(JsonKeys.DisplayRDFSLabel.name())
                .value(type.getType().getRdfsLabel())
                .key(JsonKeys.DisplayRDFSComment.name())
                .value(type.getType().getRdfsComment())
                .key(JsonKeys.DomainId.name())
                .value(domainNode.getId())
                .key(JsonKeys.DomainUri.name())
                .value(domainNode.getUri())
                .key(JsonKeys.DisplayDomainLabel.name())
                .value(domainNode.getDisplayId())
                .key(JsonKeys.DomainRDFSLabel.name())
                .value(domainNode.getRdfsLabel())
                .key(JsonKeys.DomainRDFSComment.name())
                .value(domainNode.getRdfsComment());
          } else {
            writer
                .key(JsonKeys.FullType.name())
                .value(domainNode.getId())
                .key(JsonKeys.DisplayLabel.name())
                .value(domainNode.getDisplayId())
                .key(JsonKeys.DisplayRDFSLabel.name())
                .value(domainNode.getRdfsLabel())
                .key(JsonKeys.DisplayRDFSComment.name())
                .value(domainNode.getRdfsComment())
                .key(JsonKeys.DomainId.name())
                .value("")
                .key(JsonKeys.DomainUri.name())
                .value("")
                .key(JsonKeys.DisplayDomainLabel.name())
                .value("")
                .key(JsonKeys.DomainRDFSLabel.name())
                .value("")
                .key(JsonKeys.DomainRDFSComment.name())
                .value("");
          }

          // Mark the special properties
          writer
              .key(JsonKeys.isMetaProperty.name())
              .value(isMetaProperty(type.getType(), alignmentColumnNode));

          writer.endObject();

          // Iterate through the synonym semantic types
          SynonymSemanticTypes synTypes = types.getSynonymTypesForHNodeId(nodeId);

          if (synTypes != null) {
            for (SemanticType synType : synTypes.getSynonyms()) {
              writer
                  .object()
                  .key(JsonKeys.HNodeId.name())
                  .value(synType.getHNodeId())
                  .key(JsonKeys.FullType.name())
                  .value(synType.getType().getUri())
                  .key(JsonKeys.Origin.name())
                  .value(synType.getOrigin().name())
                  .key(JsonKeys.ConfidenceLevel.name())
                  .value(synType.getConfidenceLevel().name())
                  .key(JsonKeys.DisplayLabel.name())
                  .value(synType.getType().getDisplayName())
                  .key(JsonKeys.DisplayRDFSLabel.name())
                  .value(synType.getType().getRdfsLabel())
                  .key(JsonKeys.DisplayRDFSComment.name())
                  .value(synType.getType().getRdfsComment())
                  .key(JsonKeys.isPrimary.name())
                  .value(false);
              if (!synType.isClass()) {
                writer
                    .key(JsonKeys.DomainUri.name())
                    .value(synType.getDomain().getUri())
                    .key(JsonKeys.DomainId.name())
                    .value("")
                    .key(JsonKeys.DisplayDomainLabel.name())
                    .value(synType.getDomain().getDisplayName())
                    .key(JsonKeys.DomainRDFSLabel.name())
                    .value(synType.getDomain().getRdfsLabel())
                    .key(JsonKeys.DomainRDFSComment.name())
                    .value(synType.getDomain().getRdfsComment());
              } else {
                writer
                    .key(JsonKeys.DomainId.name())
                    .value("")
                    .key(JsonKeys.DomainUri.name())
                    .value("")
                    .key(JsonKeys.DisplayDomainLabel.name())
                    .value("")
                    .key(JsonKeys.DomainRDFSLabel.name())
                    .value("")
                    .key(JsonKeys.DomainRDFSComment.name())
                    .value("");
              }
              writer.endObject();
            }
          }
          writer.endArray();
        } else {
          writer.key(JsonKeys.HNodeId.name()).value(nodeId);
          writer.key(JsonKeys.SemanticTypesArray.name()).array().endArray();
        }

        writer.endObject();
      }
      writer.endArray();
      writer.endObject();

      pw.print(writer.toString());
    } catch (JSONException e) {
      logger.error("Error occured while writing to JSON!", e);
    }
  }
  @Override
  public void generateJson(String prefix, PrintWriter pw, VWorkspace vWorkspace) {
    VWorksheet vWorksheet = vWorkspace.getViewFactory().getVWorksheetByWorksheetId(worksheetId);
    List<String> hNodeIdList = new ArrayList<String>();
    List<HNodePath> columns = vWorksheet.getColumns();
    for (HNodePath path : columns) hNodeIdList.add(path.getLeaf().getId());
    String alignmentId =
        AlignmentManager.Instance()
            .constructAlignmentId(vWorkspace.getWorkspace().getId(), vWorksheet.getWorksheetId());

    JSONObject topObj = new JSONObject();
    try {
      topObj.put(
          GenericJsonKeys.updateType.name(), AlignmentSVGVisualizationUpdate.class.getSimpleName());
      topObj.put(JsonKeys.alignmentId.name(), alignmentId);
      topObj.put(JsonKeys.worksheetId.name(), worksheetId);

      // Using Mohsen's GraphUtils method for graph traversal
      HashMap<Node, Integer> nodeHeightsMap = GraphUtil.levelingCyclicGraph(alignmentGraph);
      HashMap<Node, Set<ColumnNode>> nodeCoverage =
          GraphUtil.getNodesCoverage(alignmentGraph, nodeHeightsMap);
      /** Identify the max height * */
      int maxTreeHeight = 0;
      for (Node node : nodeHeightsMap.keySet()) {
        if (nodeHeightsMap.get(node) >= maxTreeHeight) {
          maxTreeHeight = nodeHeightsMap.get(node);
        }
      }

      /** * Add the nodes and the links from the Steiner tree ** */
      List<String> hNodeIdsAdded = new ArrayList<String>();
      JSONArray nodesArr = new JSONArray();
      JSONArray linksArr = new JSONArray();

      if (alignmentGraph != null && alignmentGraph.vertexSet().size() != 0) {
        /** Add the nodes * */
        Set<Node> nodes = alignmentGraph.vertexSet();
        HashMap<Node, Integer> verticesIndex = new HashMap<Node, Integer>();
        int nodesIndexcounter = 0;
        for (Node node : nodes) {
          /** Get info about the nodes that this node covers or sits above * */
          int height = maxTreeHeight - nodeHeightsMap.get(node);

          /** Add the hnode ids of the columns that this vertex covers * */
          JSONArray hNodeIdsCoveredByVertex = new JSONArray();
          for (Node v : nodeCoverage.get(node)) {
            if (v instanceof ColumnNode) {
              ColumnNode cNode = (ColumnNode) v;
              hNodeIdsCoveredByVertex.put(cNode.getHNodeId());
            }
          }

          String hNodeId = "";

          /** Add the semantic type information * */
          if (node instanceof ColumnNode) {
            ColumnNode cNode = (ColumnNode) node;
            hNodeId = cNode.getHNodeId();
            hNodeIdsAdded.add(cNode.getHNodeId());
          }
          JSONObject nodeObj =
              getNodeJsonObject(
                  node.getLocalId(),
                  node.getId(),
                  node.getType().name(),
                  height,
                  hNodeIdsCoveredByVertex,
                  hNodeId);
          nodesArr.put(nodeObj);
          verticesIndex.put(node, nodesIndexcounter++);
        }

        /** * Add the links ** */
        Set<Link> links = alignmentGraph.edgeSet();
        for (Link link : links) {
          Node source = link.getSource();
          Integer sourceIndex = verticesIndex.get(source);
          Node target = link.getTarget();
          Integer targetIndex = verticesIndex.get(target);
          Set<Link> outEdges = alignmentGraph.outgoingEdgesOf(target);

          if (sourceIndex == null || targetIndex == null) {
            logger.error("Edge vertex index not found!");
            continue;
          }

          JSONObject linkObj = new JSONObject();
          linkObj.put(JsonKeys.source.name(), sourceIndex);
          linkObj.put(JsonKeys.target.name(), targetIndex);
          linkObj.put(JsonKeys.sourceNodeId.name(), source.getId());
          linkObj.put(JsonKeys.targetNodeId.name(), target.getId());

          linkObj.put(JsonKeys.label.name(), link.getLabel().getLocalName());
          linkObj.put(JsonKeys.id.name(), link.getId() + "");
          linkObj.put(JsonKeys.linkStatus.name(), link.getStatus().name());
          linkObj.put(JsonKeys.linkUri.name(), link.getLabel().getUri());

          if (target.getType() == NodeType.ColumnNode && outEdges.isEmpty()) {
            linkObj.put(JsonKeys.linkType.name(), JsonValues.holderLink.name());
            if (link.getKeyType() == LinkKeyInfo.PartOfKey)
              linkObj.put(JsonKeys.label.name(), link.getLabel().getLocalName() + "*");
          }

          linksArr.put(linkObj);

          if (link.getType() == LinkType.ClassInstanceLink
              && link.getKeyType() == LinkKeyInfo.PartOfKey
              && target instanceof ColumnNode) {
            ColumnNode cNode = (ColumnNode) target;
            // Add the holder vertex object and the link that attaches nodes to the columns
            JSONArray hNodeIdsCoveredByVertex_holder = new JSONArray();
            hNodeIdsCoveredByVertex_holder.put(cNode.getHNodeId());

            JSONObject vertObj_holder =
                getNodeJsonObject(
                    JsonValues.key.name(),
                    source.getId() + "_holder",
                    NodeType.ColumnNode.name(),
                    0,
                    hNodeIdsCoveredByVertex_holder,
                    cNode.getHNodeId());
            nodesArr.put(vertObj_holder);
            nodesIndexcounter++;

            // Add the holder link
            JSONObject linkObj_holder =
                getLinkJsonObject(
                    JsonValues.key.name(),
                    "",
                    nodesIndexcounter,
                    nodesIndexcounter - 1,
                    "",
                    "",
                    "",
                    "");
            linksArr.put(linkObj_holder);
          }

          if (link.getType() == LinkType.DataPropertyOfColumnLink) {
            DataPropertyOfColumnLink dpLink = (DataPropertyOfColumnLink) link;
            String startHNodeId = dpLink.getSpecializedColumnHNodeId();

            // Get height of the class instance node
            int height = maxTreeHeight - nodeHeightsMap.get(link.getSource());

            // Add 2 more holder nodes
            // Start node
            JSONArray hNodeIdsCoveredByVertex_holder = new JSONArray();
            hNodeIdsCoveredByVertex_holder.put(startHNodeId);
            JSONObject startNode =
                getNodeJsonObject(
                    "",
                    source.getId() + "_holder",
                    JsonValues.DataPropertyOfColumnHolder.name(),
                    height - 0.35,
                    hNodeIdsCoveredByVertex_holder,
                    startHNodeId);
            nodesArr.put(startNode);

            nodesIndexcounter++;

            // End node
            String endHNodeId = ((ColumnNode) link.getTarget()).getHNodeId();
            JSONArray hNodeIdsCoveredByVertex_holder_2 = new JSONArray();
            hNodeIdsCoveredByVertex_holder_2.put(endHNodeId);
            JSONObject endNode =
                getNodeJsonObject(
                    "",
                    target.getId() + "_holder",
                    JsonValues.DataPropertyOfColumnHolder.name(),
                    height - 0.35,
                    hNodeIdsCoveredByVertex_holder_2,
                    endHNodeId);
            nodesArr.put(endNode);

            nodesIndexcounter++;

            // Add the horizontal link
            JSONObject linkObj_holder =
                getLinkJsonObject(
                    "",
                    "",
                    nodesIndexcounter - 2,
                    nodesIndexcounter - 1,
                    JsonValues.horizontalDataPropertyLink.name(),
                    "",
                    "",
                    "");
            linksArr.put(linkObj_holder);
          } else if (link.getType() == LinkType.ObjectPropertySpecializationLink) {
            ObjectPropertySpecializationLink opLink = (ObjectPropertySpecializationLink) link;
            Link specializedLink = opLink.getSpecializedLink();

            // Get height of the class instance node
            int height = nodeHeightsMap.get(specializedLink.getTarget());

            // Add 2 more holder nodes
            // Start node
            JSONArray hNodeIdsCoveredByVertex_holder = new JSONArray();
            for (Node v : nodeCoverage.get(specializedLink.getTarget())) {
              if (v instanceof ColumnNode) {
                ColumnNode cNode = (ColumnNode) v;
                hNodeIdsCoveredByVertex_holder.put(cNode.getHNodeId());
              }
            }
            JSONObject startNode =
                getNodeJsonObject(
                    "",
                    source.getId() + "_holder",
                    JsonValues.DataPropertyOfColumnHolder.name(),
                    height + 0.65,
                    hNodeIdsCoveredByVertex_holder,
                    "");
            nodesArr.put(startNode);

            nodesIndexcounter++;

            // End node
            String endHNodeId = ((ColumnNode) link.getTarget()).getHNodeId();
            JSONArray hNodeIdsCoveredByVertex_holder_2 = new JSONArray();
            hNodeIdsCoveredByVertex_holder_2.put(endHNodeId);
            JSONObject endNode =
                getNodeJsonObject(
                    "",
                    target.getId() + "_holder",
                    JsonValues.DataPropertyOfColumnHolder.name(),
                    height + 0.65,
                    hNodeIdsCoveredByVertex_holder_2,
                    endHNodeId);
            nodesArr.put(endNode);

            nodesIndexcounter++;

            // Add the horizontal link
            JSONObject linkObj_holder =
                getLinkJsonObject(
                    "",
                    "",
                    nodesIndexcounter - 2,
                    nodesIndexcounter - 1,
                    JsonValues.horizontalDataPropertyLink.name(),
                    "",
                    "",
                    "");
            linksArr.put(linkObj_holder);
          }

          linkObj.put(JsonKeys.linkType.name(), link.getType());
        }
      }

      // Add the vertices for the columns that were not in Steiner tree
      hNodeIdList.removeAll(hNodeIdsAdded);
      for (String hNodeId : hNodeIdList) {
        JSONArray hNodeIdsCoveredByVertex = new JSONArray();
        hNodeIdsCoveredByVertex.put(hNodeId);
        JSONObject vertObj =
            getNodeJsonObject(
                "", hNodeId, JsonValues.Unassigned.name(), 0, hNodeIdsCoveredByVertex, hNodeId);
        nodesArr.put(vertObj);
      }

      topObj.put(JsonKeys.maxTreeHeight.name(), maxTreeHeight);
      topObj.put(JsonKeys.nodes.name(), nodesArr);
      topObj.put(JsonKeys.links.name(), linksArr);

      pw.write(topObj.toString());
    } catch (JSONException e) {
      logger.error("Error occured while writing JSON!", e);
    }
  }
  @Override
  public UpdateContainer doIt(VWorkspace vWorkspace) throws CommandException {
    OntologyManager ontMgr = vWorkspace.getWorkspace().getOntologyManager();
    JSONArray classesList = new JSONArray();
    JSONArray classesMap = new JSONArray();
    JSONArray propertiesList = new JSONArray();
    JSONArray propertiesMap = new JSONArray();

    Map<String, String> prefixMap = vWorkspace.getWorkspace().getOntologyManager().getPrefixMap();

    ExtendedIterator<OntClass> iter = ontMgr.getOntModel().listNamedClasses();
    //		ExtendedIterator<DatatypeProperty> propsIter = ontMgr.getOntModel()
    //				.listDatatypeProperties();
    ExtendedIterator<OntProperty> propsIter = ontMgr.getOntModel().listAllOntProperties();
    final JSONObject outputObj = new JSONObject();

    try {
      while (iter.hasNext()) {
        OntClass cls = iter.next();

        String pr = prefixMap.get(cls.getNameSpace());
        String classLabel = cls.getLocalName();
        //				if (cls.getLabel(null) != null && !cls.getLabel(null).equals(""))
        //					classLabel = cls.getLabel(null);
        String clsStr = (pr != null && !pr.equals("")) ? pr + ":" + classLabel : classLabel;

        classesList.put(clsStr);
        JSONObject classKey = new JSONObject();
        classKey.put(clsStr, cls.getURI());
        classesMap.put(classKey);
      }

      while (propsIter.hasNext()) {
        //				DatatypeProperty prop = propsIter.next();
        OntProperty prop = propsIter.next();

        if (prop.isObjectProperty() && !prop.isDatatypeProperty()) continue;

        String pr = prefixMap.get(prop.getNameSpace());
        String propLabel = prop.getLocalName();
        //				if (prop.getLabel(null) != null && !prop.getLabel(null).equals(""))
        //					propLabel = prop.getLabel(null);
        String propStr = (pr != null && !pr.equals("")) ? pr + ":" + propLabel : propLabel;

        propertiesList.put(propStr);
        JSONObject propKey = new JSONObject();
        propKey.put(propStr, prop.getURI());
        propertiesMap.put(propKey);
      }

      // Populate the JSON object that will hold everything in output
      outputObj.put(JsonKeys.classList.name(), classesList);
      outputObj.put(JsonKeys.classMap.name(), classesMap);
      outputObj.put(JsonKeys.propertyList.name(), propertiesList);
      outputObj.put(JsonKeys.propertyMap.name(), propertiesMap);

    } catch (JSONException e) {
      logger.error("Error populating JSON!");
    }

    UpdateContainer upd =
        new UpdateContainer(
            new AbstractUpdate() {
              @Override
              public void generateJson(String prefix, PrintWriter pw, VWorkspace vWorkspace) {
                pw.print(outputObj.toString());
              }
            });
    return upd;
  }
 public void generateJson(String prefix, PrintWriter pw, VWorkspace vWorkspace) {
   vWorksheet.generateWorksheetHeadersJson(prefix, pw, vWorkspace.getViewFactory());
 }