/**
  * Returns human readable path for node. To improve performance may return simple toString()
  * method of the path.
  *
  * @param nodeRef
  * @return Human readable path for node
  */
 private String getNodePath(NodeRef nodeRef) {
   String result = null;
   if (nodeService.exists(nodeRef)) {
     Path path = nodeService.getPath(nodeRef);
     return path.toPrefixString(namespacePrefixResolver);
   }
   return result;
 }
  /* (non-Javadoc)
   * @see org.alfresco.service.cmr.view.Exporter#startReference(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName)
   */
  public void startReference(NodeRef nodeRef, QName childName) {
    try {
      // determine format of reference e.g. node or path based
      ReferenceType referenceFormat = referenceType;
      if (nodeRef.equals(nodeService.getRootNode(nodeRef.getStoreRef()))) {
        referenceFormat = ReferenceType.PATHREF;
      }

      // output reference
      AttributesImpl attrs = new AttributesImpl();
      if (referenceFormat.equals(ReferenceType.PATHREF)) {
        Path path = createPath(context.getExportParent(), context.getExportParent(), nodeRef);
        attrs.addAttribute(
            NamespaceService.REPOSITORY_VIEW_1_0_URI,
            PATHREF_LOCALNAME,
            PATHREF_QNAME.toPrefixString(),
            null,
            path.toPrefixString(namespaceService));
      } else {
        attrs.addAttribute(
            NamespaceService.REPOSITORY_VIEW_1_0_URI,
            NODEREF_LOCALNAME,
            NODEREF_QNAME.toPrefixString(),
            null,
            nodeRef.toString());
      }
      if (childName != null) {
        attrs.addAttribute(
            NamespaceService.REPOSITORY_VIEW_1_0_URI,
            CHILDNAME_LOCALNAME,
            CHILDNAME_QNAME.toPrefixString(),
            null,
            childName.toPrefixString(namespaceService));
      }
      contentHandler.startElement(
          REFERENCE_QNAME.getNamespaceURI(),
          REFERENCE_LOCALNAME,
          toPrefixString(REFERENCE_QNAME),
          attrs);
    } catch (SAXException e) {
      throw new ExporterException("Failed to process start reference", e);
    }
  }
  /* (non-Javadoc)
   * @see org.alfresco.service.cmr.view.Exporter#value(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, java.io.Serializable)
   */
  public void value(NodeRef nodeRef, QName property, Object value, int index) {
    try {
      // determine data type of value
      QName valueDataType = null;
      PropertyDefinition propDef = dictionaryService.getProperty(property);
      DataTypeDefinition dataTypeDef = (propDef == null) ? null : propDef.getDataType();
      if (dataTypeDef == null || dataTypeDef.getName().equals(DataTypeDefinition.ANY)) {
        dataTypeDef = (value == null) ? null : dictionaryService.getDataType(value.getClass());
        if (dataTypeDef != null) {
          valueDataType = dataTypeDef.getName();
        }
      }

      // convert node references to paths
      if (value instanceof NodeRef && referenceType.equals(ReferenceType.PATHREF)) {
        NodeRef valueNodeRef = (NodeRef) value;
        if (nodeRef.getStoreRef().equals(valueNodeRef.getStoreRef())) {
          Path nodeRefPath = createPath(context.getExportOf(), nodeRef, valueNodeRef);
          value = (nodeRefPath == null) ? null : nodeRefPath.toPrefixString(namespaceService);
        }
      }

      // output value wrapper if value is null or property data type is ANY or value is part of
      // collection
      if (value == null || valueDataType != null || index != -1) {
        AttributesImpl attrs = new AttributesImpl();
        if (value == null) {
          attrs.addAttribute(
              NamespaceService.REPOSITORY_VIEW_PREFIX,
              ISNULL_LOCALNAME,
              ISNULL_QNAME.toPrefixString(),
              null,
              "true");
        }
        if (valueDataType != null) {
          attrs.addAttribute(
              NamespaceService.REPOSITORY_VIEW_PREFIX,
              DATATYPE_LOCALNAME,
              DATATYPE_QNAME.toPrefixString(),
              null,
              toPrefixString(valueDataType));
        }
        contentHandler.startElement(
            NamespaceService.REPOSITORY_VIEW_PREFIX,
            VALUE_LOCALNAME,
            toPrefixString(VALUE_QNAME),
            attrs);
      }

      // output value
      String strValue = (String) DefaultTypeConverter.INSTANCE.convert(String.class, value);
      if (strValue != null) {
        for (int i = 0; i < strValue.length(); i++) {
          char[] temp = new char[] {strValue.charAt(i)};
          contentHandler.characters(temp, 0, 1);
        }
      }

      // output value wrapper if property data type is any
      if (value == null || valueDataType != null || index != -1) {
        contentHandler.endElement(
            NamespaceService.REPOSITORY_VIEW_PREFIX, VALUE_LOCALNAME, toPrefixString(VALUE_QNAME));
      }
    } catch (SAXException e) {
      throw new ExporterException(
          "Failed to process value event - nodeRef "
              + nodeRef
              + "; property "
              + toPrefixString(property)
              + "; value "
              + value,
          e);
    }
  }
  /**
   * Returns a list of NodeRefs representing the deployment servers configured for the given web
   * project.
   *
   * @param webProject Web project to get test servers for
   * @param live
   * @param availableOnly if true only returns those servers still available for deployment
   * @return List of test servers
   */
  private static List<NodeRef> findServers(
      NodeRef webProject, boolean live, boolean availableOnly) {
    FacesContext context = FacesContext.getCurrentInstance();
    NodeService nodeService = Repository.getServiceRegistry(context).getNodeService();
    SearchService searchService = Repository.getServiceRegistry(context).getSearchService();

    NamespacePrefixResolver namespacePrefixResolver =
        Repository.getServiceRegistry(context).getNamespaceService();

    Path projectPath = nodeService.getPath(webProject);

    String stringPath = projectPath.toPrefixString(namespacePrefixResolver);

    StringBuilder query = new StringBuilder("PATH:\"");

    query.append(stringPath);
    query.append("/*\" ");
    query.append(" AND @");
    query.append(NamespaceService.WCMAPP_MODEL_PREFIX);
    query.append("\\:");
    query.append(WCMAppModel.PROP_DEPLOYSERVERTYPE.getLocalName());
    query.append(":\"");
    if (live) {
      query.append(WCMAppModel.CONSTRAINT_LIVESERVER);
    } else {
      query.append(WCMAppModel.CONSTRAINT_TESTSERVER);
    }
    query.append("\"");

    // if required filter the test servers
    if (live == false && availableOnly) {
      query.append(" AND ISNULL:\"");
      query.append(WCMAppModel.PROP_DEPLOYSERVERALLOCATEDTO.toString());
      query.append("\"");
    }

    if (logger.isDebugEnabled())
      logger.debug("Finding deployment servers using query: " + query.toString());

    // execute the query
    ResultSet results = null;
    List<NodeRef> servers = new ArrayList<NodeRef>();
    try {
      results =
          searchService.query(
              Repository.getStoreRef(), SearchService.LANGUAGE_LUCENE, query.toString());

      if (logger.isDebugEnabled())
        logger.debug("Found " + results.length() + " deployment servers");

      for (NodeRef server : results.getNodeRefs()) {
        servers.add(server);
      }
    } finally {
      if (results != null) {
        results.close();
      }
    }

    return servers;
  }