/*
* Copyright 2008 Hippo.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hippoecm.tools.cli;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.nodetype.NodeDefinition;
import javax.jcr.nodetype.NodeType;
import javax.jcr.nodetype.PropertyDefinition;
import javax.jcr.version.OnParentVersionAction;
public class JcrCompactNodeTypeDefWriter {
private static final String INDENT = " ";
private Writer out;
public JcrCompactNodeTypeDefWriter(OutputStream outputStream) {
this.out = new OutputStreamWriter(outputStream);
}
public JcrCompactNodeTypeDefWriter(Writer out) {
this.out = out;
}
public void printNodeTypeDef(NodeType nt) throws IOException {
writeName(nt);
writeSupertypes(nt);
writeOptions(nt);
writePropDefs(nt);
writeNodeDefs(nt);
out.write("\n\n");
out.flush();
}
private void writeName(NodeType nt) throws IOException {
out.write("[");
out.write(resolve(nt.getName()));
out.write("]");
}
private void writeSupertypes(NodeType nt) throws IOException {
NodeType[] superTypes = nt.getDeclaredSupertypes();
String delim = " > ";
for (NodeType sn : superTypes) {
out.write(delim);
out.write(resolve(sn.getName()));
delim = ", ";
}
}
private void writeOptions(NodeType nt) throws IOException {
if (nt.hasOrderableChildNodes()) {
out.write("\n" + INDENT);
out.write("orderable");
if (nt.isMixin()) {
out.write(" mixin");
}
} else if (nt.isMixin()) {
out.write("\n" + INDENT);
out.write("mixin");
}
}
private void writePropDefs(NodeType nt) throws IOException {
PropertyDefinition[] propdefs = nt.getDeclaredPropertyDefinitions();
for (PropertyDefinition propdef : propdefs) {
writePropDef(nt, propdef);
}
}
private void writePropDef(NodeType nt, PropertyDefinition pd) throws IOException {
out.write("\n" + INDENT + "- ");
writeItemDefName(pd.getName());
out.write(" (");
out.write(PropertyType.nameFromValue(pd.getRequiredType()).toLowerCase());
out.write(")");
writeDefaultValues(pd.getDefaultValues());
out.write(nt.getPrimaryItemName() != null && nt.getPrimaryItemName().equals(pd.getName()) ? " primary" : "");
if (pd.isMandatory()) {
out.write(" mandatory");
}
if (pd.isAutoCreated()) {
out.write(" autocreated");
}
if (pd.isProtected()) {
out.write(" protected");
}
if (pd.isMultiple()) {
out.write(" multiple");
}
if (pd.getOnParentVersion() != OnParentVersionAction.COPY) {
out.write(" ");
out.write(OnParentVersionAction.nameFromValue(pd.getOnParentVersion()).toLowerCase());
}
writeValueConstraints(pd.getValueConstraints());
}
private void writeNodeDefs(NodeType nt) throws IOException {
NodeDefinition[] childnodeDefs = nt.getDeclaredChildNodeDefinitions();
for (NodeDefinition childnodeDef : childnodeDefs) {
writeNodeDef(nt, childnodeDef);
}
}
private void writeNodeDef(NodeType nt, NodeDefinition nd) throws IOException {
out.write("\n" + INDENT + "+ ");
String name = nd.getName();
if (name.equals("*")) {
out.write('*');
} else {
writeItemDefName(name);
}
writeRequiredTypes(nd.getRequiredPrimaryTypes());
writeDefaultType(nd.getDefaultPrimaryType());
out.write(nt.getPrimaryItemName() != null && nt.getPrimaryItemName().equals(nd.getName()) ? " primary" : "");
if (nd.isMandatory()) {
out.write(" mandatory");
}
if (nd.isAutoCreated()) {
out.write(" autocreated");
}
if (nd.isProtected()) {
out.write(" protected");
}
if (nd.allowsSameNameSiblings()) {
out.write(" multiple");
}
if (nd.getOnParentVersion() != OnParentVersionAction.COPY) {
out.write(" ");
out.write(OnParentVersionAction.nameFromValue(nd.getOnParentVersion()).toLowerCase());
}
}
private void writeRequiredTypes(NodeType[] reqTypes) throws IOException {
if (reqTypes != null && reqTypes.length > 0) {
String delim = " (";
for (int i = 0; i < reqTypes.length; i++) {
out.write(delim);
out.write(resolve(reqTypes[i].getName()));
delim = ", ";
}
out.write(")");
}
}
/**
* write default types
* @param defType
*/
private void writeDefaultType(NodeType defType) throws IOException {
if (defType != null && !defType.getName().equals("*")) {
out.write(" = ");
out.write(resolve(defType.getName()));
}
}
private void writeValueConstraints(String[] vca) throws IOException {
if (vca != null && vca.length > 0) {
String vc = vca[0];
out.write(" < '");
out.write(escape(vc));
out.write("'");
for (int i = 1; i < vca.length; i++) {
vc = vca[i];
out.write(", '");
out.write(escape(vc));
out.write("'");
}
}
}
private void writeItemDefName(String name) throws IOException {
out.write(resolve(name));
}
public static String resolve(String name) {
if (name == null) {
return "";
}
if (name.indexOf(":") > -1) {
String prefix = name.substring(0, name.indexOf(":"));
if (!"".equals(prefix)) {
prefix += ":";
}
String encLocalName = /*ISO9075Helper.encodeLocalName(*/name.substring(name.indexOf(":") + 1)/*)*/;
String resolvedName = prefix + encLocalName;
// check for '-' and '+'
if (resolvedName.indexOf('-') >= 0 || resolvedName.indexOf('+') >= 0) {
return "'" + resolvedName + "'";
} else {
return resolvedName;
}
} else {
return name;
}
}
public static String escape(String s) {
StringBuffer sb = new StringBuffer(s);
for (int i = 0; i < sb.length(); i++) {
if (sb.charAt(i) == '\\') {
sb.insert(i, '\\');
i++;
} else if (sb.charAt(i) == '\'') {
sb.insert(i, '\'');
i++;
}
}
return sb.toString();
}
private void writeDefaultValues(Value[] dva) throws IOException {
if (dva != null && dva.length > 0) {
String delim = " = '";
for (int i = 0; i < dva.length; i++) {
out.write(delim);
try {
out.write(escape(dva[i].getString()));
} catch (RepositoryException e) {
out.write(escape(dva[i].toString()));
}
out.write("'");
delim = ", '";
}
}
}
}