| /******************************************************************************* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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.apache.olingo.odata2.core.uri; |
| |
| import java.io.IOException; |
| import java.io.StringWriter; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.apache.olingo.odata2.api.edm.EdmEntitySet; |
| import org.apache.olingo.odata2.api.edm.EdmEntityType; |
| import org.apache.olingo.odata2.api.edm.EdmException; |
| import org.apache.olingo.odata2.api.edm.EdmNavigationProperty; |
| import org.apache.olingo.odata2.api.edm.EdmProperty; |
| import org.apache.olingo.odata2.api.edm.EdmTyped; |
| import org.apache.olingo.odata2.api.uri.ExpandSelectTreeNode; |
| import org.apache.olingo.odata2.core.ep.util.JsonStreamWriter; |
| import org.apache.olingo.odata2.core.exception.ODataRuntimeException; |
| |
| /** |
| * |
| */ |
| public class ExpandSelectTreeNodeImpl extends ExpandSelectTreeNode { |
| |
| public enum AllKinds { |
| IMPLICITLYTRUE(true), EXPLICITLYTRUE(true), FALSE(false); |
| |
| private boolean booleanRepresentation; |
| |
| private AllKinds(final boolean booleanRepresentation) { |
| this.booleanRepresentation = booleanRepresentation; |
| } |
| |
| public boolean getBoolean() { |
| return booleanRepresentation; |
| } |
| } |
| |
| private AllKinds isAll = AllKinds.IMPLICITLYTRUE; |
| private boolean isExplicitlySelected = false; |
| private boolean isExpanded = false; |
| private final List<EdmProperty> properties = new ArrayList<EdmProperty>(); |
| private final Map<String, ExpandSelectTreeNodeImpl> links = new HashMap<String, ExpandSelectTreeNodeImpl>(); |
| private final List<ExpandSelectTreeNode> expandselectTreeNodes = new ArrayList<ExpandSelectTreeNode>(); |
| |
| @Override |
| public boolean isAll() { |
| return isAll.getBoolean(); |
| } |
| |
| @Override |
| public List<EdmProperty> getProperties() { |
| return properties; |
| } |
| |
| @SuppressWarnings("unchecked") |
| @Override |
| public Map<String, ExpandSelectTreeNode> getLinks() { |
| return (Map<String, ExpandSelectTreeNode>) ((Map<String, ? extends ExpandSelectTreeNode>) Collections |
| .unmodifiableMap(links)); |
| } |
| |
| @Override |
| public List<ExpandSelectTreeNode> getExpandedList() { |
| return expandselectTreeNodes; |
| } |
| |
| public void putLink(final String name, final ExpandSelectTreeNodeImpl node) { |
| links.put(name, node); |
| } |
| |
| public void removeLink(final String name) { |
| links.remove(name); |
| } |
| |
| public boolean isExplicitlySelected() { |
| return isExplicitlySelected; |
| } |
| |
| public void setExplicitlySelected() { |
| isExplicitlySelected = true; |
| setAllExplicitly(); |
| } |
| |
| public boolean isExpanded() { |
| return isExpanded; |
| } |
| |
| public void setExpanded() { |
| isExpanded = true; |
| } |
| |
| public void addProperty(final EdmProperty property) { |
| if (property != null && isAll != AllKinds.EXPLICITLYTRUE && !properties.contains(property)) { |
| properties.add(property); |
| isAll = AllKinds.FALSE; |
| } |
| } |
| |
| public void setAllExplicitly() { |
| properties.clear(); |
| isAll = AllKinds.EXPLICITLYTRUE; |
| } |
| |
| public AllKinds getAllKind() { |
| return isAll; |
| } |
| |
| public void setAllKindFalse() { |
| isAll = AllKinds.FALSE; |
| } |
| |
| public String toJsonString() { |
| try { |
| StringWriter writer = new StringWriter(); |
| JsonStreamWriter jsonStreamWriter = new JsonStreamWriter(writer); |
| jsonStreamWriter.beginObject() |
| .name("all").unquotedValue(Boolean.toString(isAll())).separator() |
| .name("properties") |
| .beginArray(); |
| boolean first = true; |
| for (EdmProperty property : properties) { |
| if (first) { |
| first = false; |
| } else { |
| jsonStreamWriter.separator(); |
| } |
| jsonStreamWriter.stringValueRaw(property.getName()); |
| } |
| jsonStreamWriter.endArray().separator() |
| .name("links") |
| .beginArray(); |
| first = true; |
| for (Map.Entry<String, ExpandSelectTreeNodeImpl> entry : links.entrySet()) { |
| if (first) { |
| first = false; |
| } else { |
| jsonStreamWriter.separator(); |
| } |
| final String nodeString = entry.getValue() == null ? null : entry.getValue().toJsonString(); |
| jsonStreamWriter.beginObject() |
| .name(entry.getKey()).unquotedValue(nodeString) |
| .endObject(); |
| } |
| jsonStreamWriter.endArray() |
| .endObject(); |
| writer.flush(); |
| return writer.toString(); |
| } catch (final IOException e) { |
| throw new ODataRuntimeException("IOException: ", e); |
| } catch (final EdmException e) { |
| throw new ODataRuntimeException("EdmException: ", e); |
| } |
| } |
| |
| public class ExpandSelectTreeNodeBuilderImpl extends ExpandSelectTreeNodeBuilder { |
| |
| private EdmEntitySet entitySet; |
| private List<String> selectedPropertyNames; |
| private List<String> selectedNavigationPropertyNames; |
| private Map<String, ExpandSelectTreeNode> customExpandedNavigationProperties; |
| private List<String> expandedNavigationPropertyNames; |
| |
| @Override |
| public ExpandSelectTreeNodeBuilder entitySet(final EdmEntitySet entitySet) { |
| this.entitySet = entitySet; |
| return this; |
| } |
| |
| @Override |
| public ExpandSelectTreeNode build() throws EdmException { |
| EdmEntityType entityType = entitySet.getEntityType(); |
| if (selectedPropertyNames != null) { |
| handleProperties(entityType); |
| } |
| |
| if (selectedNavigationPropertyNames != null) { |
| setAllKindFalse(); |
| handleLinks(entityType, selectedNavigationPropertyNames, null); |
| } |
| |
| if (expandedNavigationPropertyNames != null) { |
| ExpandSelectTreeNodeImpl subNode = new ExpandSelectTreeNodeImpl(); |
| subNode.setExplicitlySelected(); |
| handleLinks(entityType, expandedNavigationPropertyNames, subNode); |
| } |
| |
| if (customExpandedNavigationProperties != null) { |
| handleCustomLinks(entityType); |
| } |
| |
| return ExpandSelectTreeNodeImpl.this; |
| } |
| |
| private void handleCustomLinks(final EdmEntityType entityType) throws EdmException { |
| for (Map.Entry<String, ExpandSelectTreeNode> entry : customExpandedNavigationProperties.entrySet()) { |
| EdmTyped navigationProperty = entityType.getProperty(entry.getKey()); |
| if (navigationProperty == null) { |
| throw new EdmException(EdmException.NAVIGATIONPROPERTYNOTFOUND.addContent(entry.getKey())); |
| } |
| if (!(navigationProperty instanceof EdmNavigationProperty)) { |
| throw new EdmException(EdmException.MUSTBENAVIGATIONPROPERTY.addContent(entry.getKey())); |
| } |
| putLink(entry.getKey(), (ExpandSelectTreeNodeImpl) entry.getValue()); |
| } |
| } |
| |
| private void handleLinks(final EdmEntityType entityType, final List<String> names, |
| final ExpandSelectTreeNodeImpl subNode) throws EdmException { |
| for (String navigationPropertyName : names) { |
| EdmTyped navigationProperty = entityType.getProperty(navigationPropertyName); |
| if (navigationProperty == null) { |
| throw new EdmException(EdmException.NAVIGATIONPROPERTYNOTFOUND.addContent(navigationPropertyName)); |
| } else if (!(navigationProperty instanceof EdmNavigationProperty)) { |
| throw new EdmException(EdmException.MUSTBENAVIGATIONPROPERTY.addContent(navigationPropertyName)); |
| } |
| putLink(navigationPropertyName, subNode); |
| } |
| } |
| |
| private void handleProperties(final EdmEntityType entityType) throws EdmException { |
| for (String propertyName : selectedPropertyNames) { |
| EdmTyped property = entityType.getProperty(propertyName); |
| if (property == null) { |
| throw new EdmException(EdmException.PROPERTYNOTFOUND.addContent(propertyName)); |
| } else if (!(property instanceof EdmProperty)) { |
| throw new EdmException(EdmException.MUSTBEPROPERTY.addContent(propertyName)); |
| } |
| addProperty((EdmProperty) property); |
| } |
| } |
| |
| @Override |
| public ExpandSelectTreeNodeBuilder selectedProperties(final List<String> selectedPropertyNames) { |
| this.selectedPropertyNames = selectedPropertyNames; |
| return this; |
| } |
| |
| @Override |
| public ExpandSelectTreeNodeBuilder selectedLinks(final List<String> selectedNavigationPropertyNames) { |
| this.selectedNavigationPropertyNames = selectedNavigationPropertyNames; |
| return this; |
| } |
| |
| @Override |
| public ExpandSelectTreeNodeBuilder |
| customExpandedLink(final String navigationPropertyName, final ExpandSelectTreeNode expandNode) { |
| if (expandNode == null) { |
| throw new ODataRuntimeException("ExpandNode must not be null"); |
| } |
| if (customExpandedNavigationProperties == null) { |
| customExpandedNavigationProperties = new HashMap<String, ExpandSelectTreeNode>(); |
| } |
| customExpandedNavigationProperties.put(navigationPropertyName, expandNode); |
| return this; |
| } |
| |
| @Override |
| public ExpandSelectTreeNodeBuilder expandedLinks(final List<String> navigationPropertyNames) { |
| expandedNavigationPropertyNames = navigationPropertyNames; |
| return this; |
| } |
| |
| } |
| } |