001/*
002 * ModeShape (http://www.modeshape.org)
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 */
016package org.modeshape.jdbc.rest;
017
018import java.util.HashSet;
019import java.util.Set;
020import javax.jcr.version.OnParentVersionAction;
021import org.codehaus.jettison.json.JSONObject;
022import org.modeshape.common.annotation.Immutable;
023import org.modeshape.common.util.HashCode;
024
025/**
026 * A {@link javax.jcr.nodetype.NodeDefinition} implementation for the Modeshape client.
027 */
028@Immutable
029public class ChildNodeDefinition extends ItemDefinition implements javax.jcr.nodetype.NodeDefinition {
030
031    private final Id id;
032    private final String defaultPrimaryTypeName;
033
034    protected ChildNodeDefinition( String declaringNodeTypeName,
035                                   JSONObject json,
036                                   NodeTypes nodeTypes ) {
037        super(declaringNodeTypeName, json, nodeTypes);
038
039        String name = JSONHelper.valueFrom(json, "jcr:name", "*");
040        boolean allowsSns = JSONHelper.valueFrom(json, "jcr:sameNameSiblings", false);
041        Set<String> requiredTypes = new HashSet<>(JSONHelper.valuesFrom(json, "jcr:requiredPrimaryTypes"));
042        this.id = new Id(name, allowsSns, requiredTypes);
043        this.defaultPrimaryTypeName = JSONHelper.valueFrom(json, "jcr:defaultPrimaryType");
044    }
045
046    protected Id id() {
047        return id;
048    }
049
050    @Override
051    public String getName() {
052        return id.name;
053    }
054
055    @Override
056    public boolean allowsSameNameSiblings() {
057        return id.isMultiple;
058    }
059
060    @Override
061    public String[] getRequiredPrimaryTypeNames() {
062        return id.requiredTypes.toArray(new String[id.requiredTypes.size()]);
063    }
064
065    @Override
066    public NodeType getDefaultPrimaryType() {
067        return nodeTypes().getNodeType(getDefaultPrimaryTypeName());
068    }
069
070    @Override
071    public String getDefaultPrimaryTypeName() {
072        return defaultPrimaryTypeName;
073    }
074
075    @Override
076    public javax.jcr.nodetype.NodeType[] getRequiredPrimaryTypes() {
077        return nodeTypes().toNodeTypes(id.requiredTypes);
078    }
079
080    @Override
081    public int hashCode() {
082        return id.hashCode();
083    }
084
085    @Override
086    public boolean equals( Object obj ) {
087        if (obj == this) return true;
088        if (obj instanceof ChildNodeDefinition) {
089            ChildNodeDefinition that = (ChildNodeDefinition)obj;
090            return this.id.equals(that.id);
091        }
092        return false;
093    }
094
095    @Override
096    public String toString() {
097        StringBuilder sb = new StringBuilder();
098        sb.append(" + ");
099        sb.append(id.name);
100        if (getRequiredPrimaryTypeNames().length != 0) {
101            sb.append(" (");
102            boolean first = true;
103            for (String typeName : getRequiredPrimaryTypeNames()) {
104                if (typeName == null) continue;
105                if (first) first = false;
106                else sb.append(',');
107                sb.append(typeName);
108            }
109            sb.append(')');
110        }
111        if (getDefaultPrimaryTypeName() != null) {
112            sb.append(" = ").append(getDefaultPrimaryTypeName());
113        }
114        if (isAutoCreated()) sb.append(" autocreated");
115        if (isMandatory()) sb.append(" mandatory");
116        if (allowsSameNameSiblings()) sb.append(" sns");
117        if (isProtected()) sb.append(" protected");
118        sb.append(' ').append(OnParentVersionAction.nameFromValue(getOnParentVersion()));
119        return sb.toString();
120    }
121
122    protected static class Id {
123        protected final String name;
124        protected final boolean isMultiple;
125        protected final Set<String> requiredTypes;
126
127        protected Id( String name,
128                      boolean isMultiple,
129                      Set<String> requiredTypes ) {
130            this.name = name;
131            this.isMultiple = isMultiple;
132            this.requiredTypes = requiredTypes;
133            assert this.name != null;
134            assert this.requiredTypes != null;
135        }
136
137
138        @Override
139        public int hashCode() {
140            return HashCode.compute(isMultiple, name, requiredTypes);
141        }
142
143        @Override
144        public boolean equals( Object obj ) {
145            if (obj == this) return true;
146            if (obj instanceof Id) {
147                Id that = (Id)obj;
148                if (this.isMultiple != that.isMultiple) return false;
149                if (!this.requiredTypes.equals(that.requiredTypes)) return false;
150                if (!this.name.equals(that.name)) return false;
151                return true;
152            }
153            return false;
154        }
155
156        @Override
157        public String toString() {
158            StringBuilder sb = new StringBuilder(name);
159            sb.append('(');
160            boolean first = true;
161            for (String requiredType : requiredTypes) {
162                if (first) first = false;
163                else sb.append(',');
164                sb.append(requiredType);
165            }
166            sb.append(')');
167            sb.append(isMultiple ? '*' : '1');
168            return sb.toString();
169        }
170    }
171}