/*
* TeleStax, Open Source Cloud Communications
* Copyright 2011-2016, TeleStax Inc. and individual contributors
* by the @authors tag.
*
* This program is free software: you can redistribute it and/or modify
* 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/>
*
* This file incorporates work covered by the following copyright and
* permission notice:
*
* JBoss, Home of Professional Open Source
* Copyright 2007-2011, Red Hat, Inc. and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.mobicents.diameter.dictionary;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.jdiameter.common.impl.validation.AvpRepresentationImpl;
/**
* @author <a href="mailto:brainslog@gmail.com"> Alexandre Mendonca </a>
* @author <a href="mailto:baranowb@gmail.com">Bartosz Baranowski </a>
*/
public class AvpRepresentation {
/**
* <pre>
* Represents multiplicity of AVP:
* 0 The AVP MUST NOT be present in the message.
* </pre>
*/
public static final String _MP_NOT_ALLOWED = "0";
/**
* <pre>
* Represents multiplicity of AVP:
* 0+ Zero or more instances of the AVP MAY be present in the
* message.
* </pre>
*/
public static final String _MP_ZERO_OR_MORE = "0+";
/**
* <pre>
* Represents multiplicity of AVP:
* 0-1 Zero or one instance of the AVP MAY be present in the
* message. It is considered an error if there are more than
* one instance of the AVP.
* </pre>
*/
public static final String _MP_ZERO_OR_ONE = "0-1";
/**
* <pre>
* Represents multiplicity of AVP:
* 1 One instance of the AVP MUST be present in the message.
* message.
* </pre>
*/
public static final String _MP_ONE = "1";
/**
* <pre>
* Represents multiplicity of AVP:
* 1+ At least one instance of the AVP MUST be present in the
* message.
* </pre>
*/
public static final String _MP_ONE_AND_MORE = "1+";
public static final String _DEFAULT_MANDATORY = "may";
public static final String _DEFAULT_PROTECTED = "may";
public static final String _DEFAULT_VENDOR = "mustnot";
public static final int _FIX_POSITION_INDEX = -1;
public enum Rule {
must, may, mustnot, shouldnot
};
public enum Type {
OctetString, Integer32, Integer64, Unsigned32, Unsigned64, Float32, Float64, Grouped,
Address, Time, UTF8String, DiameterIdentity, DiameterURI, Enumerated, IPFilterRule, QoSFilterRule
};
protected String description;
protected boolean mayEncrypt;
protected boolean _protected;
protected boolean _mandatory;
protected String ruleMandatory;
protected String ruleProtected;
protected String ruleVendorBit;
protected String type; // String, in case user defines his own type
// ususally this will be -1, as only SessionId has fixed position
private int positionIndex = _FIX_POSITION_INDEX;
protected int code = -1;
protected long vendor = 0;
protected boolean allowed = true;
protected String multiplicityIndicator = "0";
protected String name = "Some-AVP";
protected boolean grouped = false;
protected List<AvpRepresentation> children = new ArrayList<AvpRepresentation>();
protected boolean weak = false;
/**
* @param code
* @param vendor
*/
public AvpRepresentation(int code, long vendor) {
super();
this.code = code;
this.vendor = vendor;
}
AvpRepresentation(AvpRepresentationImpl clone) {
this(-1, clone.getCode(), clone.getVendorId(), clone.getMultiplicityIndicator(), clone.getName());
this.allowed = clone.isAllowed();
this.grouped = clone.isGrouped();
this.positionIndex = clone.getPositionIndex();
this.weak = clone.isWeak();
this._mandatory = clone.isMandatory();
this._protected = clone.isProtected();
this.description = clone.getDescription();
this.mayEncrypt = clone.isMayEncrypt();
this.ruleMandatory = clone.getRuleMandatory();
this.ruleProtected = clone.getRuleProtected();
this.ruleVendorBit = clone.getRuleVendorBit();
this.type = clone.getType();
if (this.multiplicityIndicator.equals(_MP_NOT_ALLOWED)) {
this.allowed = false;
}
// copy others.
if (isGrouped()) {
for (Object o : clone.getChildren()) {
AvpRepresentationImpl avpImpl = (AvpRepresentationImpl) o;
this.children.add(new AvpRepresentation(avpImpl));
}
this.children = Collections.unmodifiableList(this.children);
}
}
AvpRepresentation(int positionIndex, int code, long vendor, String multiplicityIndicator, String name) {
super();
this.positionIndex = positionIndex;
this.code = code;
this.vendor = vendor;
this.multiplicityIndicator = multiplicityIndicator;
this.name = name;
if (this.multiplicityIndicator.equals(_MP_NOT_ALLOWED)) {
this.allowed = false;
}
}
public boolean isPositionFixed() {
return this.positionIndex == _FIX_POSITION_INDEX;
}
public void markFixPosition(int index) {
this.positionIndex = index;
}
public static int get_FIX_POSITION_INDEX() {
return _FIX_POSITION_INDEX;
}
public int getPositionIndex() {
return positionIndex;
}
public int getCode() {
return code;
}
public long getVendorId() {
return vendor;
}
public boolean isAllowed() {
return allowed;
}
public boolean isAllowed(int avpCode, long vendorId) {
if (this.isGrouped()) {
// make better get ?
for (AvpRepresentation rep : this.children) {
if (rep.getCode() == avpCode && rep.getVendorId() == vendorId) {
return rep.isAllowed();
} else {
continue;
}
}
return true;
} else {
return false;
}
}
public boolean isAllowed(int avpCode) {
return this.isAllowed(avpCode, 0L);
}
public String getMultiplicityIndicator() {
return multiplicityIndicator;
}
public String getName() {
return name;
}
public boolean isGrouped() {
return grouped;
}
public List<AvpRepresentation> getChildren() {
return children;
}
public boolean isWeak() {
return weak;
}
public String getDescription() {
return description;
}
public boolean isMayEncrypt() {
return mayEncrypt;
}
public String getRuleMandatory() {
return ruleMandatory;
}
public int getRuleMandatoryAsInt() {
return Rule.valueOf(ruleMandatory).ordinal();
}
public String getRuleProtected() {
return ruleProtected;
}
public int getRuleProtectedAsInt() {
return Rule.valueOf(ruleProtected).ordinal();
}
public String getRuleVendorBit() {
return ruleVendorBit;
}
public int getRuleVendorBitAsInt() {
return Rule.valueOf(ruleVendorBit).ordinal();
}
public String getType() {
return type;
}
public boolean isProtected() {
return _protected;
}
public boolean isMandatory() {
return _mandatory;
}
public boolean isCountValidForMultiplicity(int avpCount) {
// This covers not_allowed
if (!allowed) {
if (avpCount == 0) {
return true;
}
} else {
if (this.multiplicityIndicator.equals(_MP_ZERO_OR_MORE)) {
if (avpCount >= 0) {
return true;
}
} else if (this.multiplicityIndicator.equals(_MP_ZERO_OR_ONE)) {
if ((avpCount == 0) || (avpCount == 1)) {
return true;
}
} else if (this.multiplicityIndicator.equals(_MP_ONE)) {
if (avpCount == 1) {
return true;
}
} else if (this.multiplicityIndicator.equals(_MP_ONE_AND_MORE)) {
if (avpCount >= 1) {
return true;
}
}
}
// if we did not return, we are screwed.
return false;
}
// public String toString() {
// return this.getName() + "@" + hashCode() + " Name[" + getName() +
// "] Code[" + getCode() + "] Vendor[" + getVendorId() + "] MLP[" +
// getMultiplicityIndicator() + "] Allowed[" + isAllowed() + "] ";
// }
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("name: ").append(this.getName()).append(", code: ").append(this.getCode()).append(", vendor: ").append(this.getVendorId()).append(", weak: ")
.append(this.isWeak()).append(", grouped: ").append(this.isGrouped()).append(", type: ").append(this.getType()).append(", multiplicity: ")
.append(this.getMultiplicityIndicator());
if (this.isGrouped()) {
for (AvpRepresentation child : this.getChildren()) {
String childStr = child.toString().replace("\n", "\n---");
sb.append("\n---" + childStr);
}
}
return sb.toString();
}
@Override
public int hashCode() {
// code+vendor is enough by AVP def
final int prime = 31;
int result = 1;
result = prime * result + code;
result = prime * result + (int) (vendor ^ (vendor >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
// code+vendor is enough by AVP def
AvpRepresentation other = (AvpRepresentation) obj;
if (code != other.code) {
return false;
}
if (vendor != other.vendor) {
return false;
}
return true;
}
}