/* * Copyright (C) 2003-2011 eXo Platform SAS. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.etk.orm.plugins.bean.typegen; import java.io.Writer; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; /** * Created by The eXo Platform SAS * Author : eXoPlatform * exo@exoplatform.com * Jul 13, 2011 */ public abstract class NodeTypeSerializer { private static final Map<String, String> DEFAULT_MAPPINGS; static { HashMap<String, String> def = new HashMap<String, String>(); // def.put("nt", "http://www.jcp.org/jcr/nt/1.0"); def.put("mix", "http://www.jcp.org/jcr/mix/1.0"); def.put("jcr", "http://www.jcp.org/jcr/1.0"); // DEFAULT_MAPPINGS = Collections.unmodifiableMap(def); } /** . */ private final LinkedHashMap<String, NodeType> nodeTypes; /** . */ private final Map<String, String> mappings; /** . */ private boolean generatedUndeclaredNodeType; public NodeTypeSerializer(List<NodeType> nodeTypes, Map<String, String> mappings) { if (nodeTypes == null) { throw new NullPointerException(); } // mappings = new HashMap<String, String>(mappings); mappings.putAll(DEFAULT_MAPPINGS); // this.nodeTypes = new LinkedHashMap<String, NodeType>(); this.mappings = mappings; this.generatedUndeclaredNodeType = false; // for (NodeType nodeType : nodeTypes) { addNodeType(nodeType); } } public NodeTypeSerializer(List<NodeType> nodeTypes) { this(nodeTypes, Collections.<String, String>emptyMap()); } public NodeTypeSerializer(Map<String, String> mappings) { this(Collections.<NodeType>emptyList(), mappings); } protected NodeTypeSerializer() { this(Collections.<NodeType>emptyList(), Collections.<String, String>emptyMap()); } /** * Returns true if the serializer should generate the declarations for the undeclared node types. * * @return the generatedUndeclaredNodeType value */ public boolean getGeneratedUndeclaredNodeType() { return generatedUndeclaredNodeType; } /** * Updates the generatedUndeclaredNodeType value. * * @param generatedUndeclaredNodeType the new generatedUndeclaredNodeType value */ public void setGeneratedUndeclaredNodeType(boolean generatedUndeclaredNodeType) { this.generatedUndeclaredNodeType = generatedUndeclaredNodeType; } public void addNodeType(NodeType nodeType) { if (nodeType == null) { throw new NullPointerException("No node type provided"); } nodeTypes.put(nodeType.getName(), nodeType); } public void addPrefixMapping(String namespacePrefix, String namespaceURI) { if (namespacePrefix == null) { throw new NullPointerException("No null namespace prefix accepted"); } if (namespaceURI == null) { throw new NullPointerException("No null namespace uri accepted"); } // mappings.put(namespacePrefix, namespaceURI); } public abstract void writeTo(Writer writer) throws Exception; public final void writeTo() throws Exception { startNodeTypes(Collections.unmodifiableMap(mappings)); // Set<String> done = new HashSet<String>(); Set<String> queued = new HashSet<String>(); // for (NodeType nodeType : nodeTypes.values()) { write(nodeType, done, queued); } // endNodeTypes(); } public void write(NodeType nodeType, Set<String> done, Set<String> queued) throws Exception { // We are already done if (done.contains(nodeType.getName())) { return; } // This means a cycle if (queued.contains(nodeType.getName())) { throw new AssertionError(); } // Update context : -> queued queued.add(nodeType.getName()); // Take care of super types as dependencies for (NodeType superType : nodeType.getSuperTypes()) { write(superType, done, queued); } // Take care of children as dependencies for (NodeDefinition childDef : nodeType.getChildNodeDefinitions().values()) { NodeType childDefNodeType = nodeTypes.get(childDef.getNodeTypeName()); if (childDefNodeType == nodeType) { // Recursive / do nothing } else if (childDefNodeType != null) { write(childDefNodeType, done, queued); } } // Now process output if (nodeType.isDeclared() || generatedUndeclaredNodeType) { write(nodeType); } // Update context : queued -> done queued.remove(nodeType.getName()); done.add(nodeType.getName()); } private void write(NodeType nodeType) throws Exception { LinkedHashSet<String> superTypeNames = new LinkedHashSet<String>(); // Add nt:base if necessary if (nodeType.declaredSuperTypes.isEmpty()) { superTypeNames.add("nt:base"); } // Add super node types for (NodeType superType : nodeType.declaredSuperTypes) { superTypeNames.add(superType.getName()); } // Add mix:referenceable if required if (nodeType.isReferenceable()) { superTypeNames.add("mix:referenceable"); } // startNodeType( nodeType.getClassName(), nodeType.getName(), nodeType.isMixin(), nodeType.isOrderable(), superTypeNames ); // startProperties(); // for (PropertyDefinition propertyDefinition : nodeType.getPropertyDefinitions().values()) { property( propertyDefinition.getName(), propertyDefinition.getType(), propertyDefinition.isMultiple(), propertyDefinition.getDefaultValues(), propertyDefinition.getValueConstraints() ); } // endProperties(); // startChildNodes(); // for (NodeDefinition childNodeDefinition : nodeType.getChildNodeDefinitions().values()) { childNode( childNodeDefinition.getName(), childNodeDefinition.getNodeTypeName(), childNodeDefinition.isMandatory(), childNodeDefinition.isAutocreated()); } // endChildNodes(); // endNodeType(); } public void startNodeTypes(Map<String, String> mappings) throws Exception { } public void startNodeType( String javaClassName, String name, boolean mixin, boolean orderableChildNodes, Collection<String> superTypeNames) throws Exception { } public void startProperties() throws Exception { } public void property( String name, int requiredType, boolean multiple, Collection<String> defaultValues, Collection<String> valueConstraints) throws Exception { } public void endProperties() throws Exception { } public void startChildNodes() throws Exception { } public void childNode( String name, String nodeTypeName, boolean mandatory, boolean autocreated) throws Exception { } public void endChildNodes() throws Exception { } public void endNodeType() throws Exception { } public void endNodeTypes() throws Exception { } }