001/* 002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Nuxeo - initial API and implementation 018 * 019 * $Id$ 020 */ 021 022package org.nuxeo.ecm.core.schema; 023 024import org.apache.commons.lang.StringUtils; 025import org.nuxeo.common.xmap.annotation.XNode; 026import org.nuxeo.common.xmap.annotation.XNodeList; 027import org.nuxeo.common.xmap.annotation.XObject; 028 029import java.util.ArrayList; 030import java.util.Arrays; 031import java.util.List; 032 033/** 034 * Document Type Descriptor. 035 * <p> 036 * Can be used to delay document type registration when not all prerequisites are met (e.g. supertype was not yet 037 * registered). 038 * <p> 039 * In this case the descriptor containing all the information needed to register the document is put in a queue waiting 040 * for the prerequisites to be met. 041 * 042 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> 043 */ 044@XObject("doctype") 045public class DocumentTypeDescriptor { 046 047 @XNode("@name") 048 public String name; 049 050 @XNodeList(value = "schema", type = SchemaDescriptor[].class, componentType = SchemaDescriptor.class) 051 public SchemaDescriptor[] schemas; 052 053 @XNode("@extends") 054 public String superTypeName; 055 056 @XNodeList(value = "facet@name", type = String[].class, componentType = String.class) 057 public String[] facets; 058 059 @XNode("prefetch") 060 public String prefetch; 061 062 @XNode("@append") 063 public boolean append = false; 064 065 @XNodeList(value = "subtypes/type", type = String[].class, componentType = String.class) 066 public String[] subtypes = new String[0]; 067 068 @XNodeList(value = "subtypes-forbidden/type", type = String[].class, componentType = String.class) 069 public String[] forbiddenSubtypes = new String[0]; 070 071 public DocumentTypeDescriptor() { 072 } 073 074 public DocumentTypeDescriptor(String superTypeName, String name, SchemaDescriptor[] schemas, String[] facets) { 075 this.name = name; 076 this.superTypeName = superTypeName; 077 this.schemas = schemas; 078 this.facets = facets; 079 } 080 081 public DocumentTypeDescriptor(String superTypeName, String name, SchemaDescriptor[] schemas, String[] facets, 082 String[] subtypes, String[] forbiddenSubtypes) { 083 this(superTypeName, name, schemas, facets); 084 this.subtypes = subtypes; 085 this.forbiddenSubtypes = forbiddenSubtypes; 086 } 087 088 @Override 089 public String toString() { 090 return "DocType: " + name; 091 } 092 093 public DocumentTypeDescriptor clone() { 094 DocumentTypeDescriptor clone = new DocumentTypeDescriptor(); 095 clone.name = name; 096 clone.schemas = schemas; 097 clone.superTypeName = superTypeName; 098 clone.facets = facets; 099 clone.prefetch = prefetch; 100 clone.append = append; 101 clone.subtypes = subtypes; 102 clone.forbiddenSubtypes = forbiddenSubtypes; 103 return clone; 104 } 105 106 public DocumentTypeDescriptor merge(DocumentTypeDescriptor other) { 107 // only merge schemas, facets and prefetch 108 if (schemas == null) { 109 schemas = other.schemas; 110 } else { 111 if (other.schemas != null) { 112 List<SchemaDescriptor> mergedSchemas = new ArrayList<SchemaDescriptor>(Arrays.asList(schemas)); 113 mergedSchemas.addAll(Arrays.asList(other.schemas)); 114 schemas = mergedSchemas.toArray(new SchemaDescriptor[mergedSchemas.size()]); 115 } 116 } 117 if (facets == null) { 118 facets = other.facets; 119 } else { 120 if (other.facets != null) { 121 List<String> mergedFacets = new ArrayList<String>(Arrays.asList(facets)); 122 mergedFacets.addAll(Arrays.asList(other.facets)); 123 facets = mergedFacets.toArray(new String[mergedFacets.size()]); 124 } 125 } 126 if (prefetch == null) { 127 prefetch = other.prefetch; 128 } else { 129 if (other.prefetch != null) { 130 prefetch = prefetch + " " + other.prefetch; 131 } 132 } 133 134 // update supertype 135 if (StringUtils.isEmpty(superTypeName) && StringUtils.isNotEmpty(other.superTypeName)) { 136 superTypeName = other.superTypeName; 137 } 138 139 // merge subtypes 140 if (subtypes == null) { 141 subtypes = other.subtypes; 142 } else if (other.subtypes != null) { 143 List<String> mergedTypes = new ArrayList<>(Arrays.asList(subtypes)); 144 mergedTypes.addAll(Arrays.asList(other.subtypes)); 145 subtypes = mergedTypes.toArray(new String[mergedTypes.size()]); 146 } 147 if (forbiddenSubtypes == null) { 148 forbiddenSubtypes = other.forbiddenSubtypes; 149 } else if (other.forbiddenSubtypes != null) { 150 List<String> mergedTypes = new ArrayList<>(Arrays.asList(forbiddenSubtypes)); 151 mergedTypes.addAll(Arrays.asList(other.forbiddenSubtypes)); 152 forbiddenSubtypes = mergedTypes.toArray(new String[mergedTypes.size()]); 153 } 154 155 return this; 156 } 157 158}