/*
* 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.directory.studio.openldap.config.model.overlay;
import java.text.ParseException;
import org.apache.directory.api.util.Position;
import org.apache.directory.api.util.Strings;
/**
* This class represents 'olcRwmMap' value.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
public class OlcRwmMapValue
{
/** The constant string for '*' */
private static final String STAR_STRING = "*";
/** The type */
private OlcRwmMapValueTypeEnum type;
/** The local name */
private String localName;
/** The foreign name */
private String foreignName;
/**
* Gets the type.
*
* @return the type
*/
public OlcRwmMapValueTypeEnum getType()
{
return type;
}
/**
* Gets the local name.
*
* @return the local name
*/
public String getLocalName()
{
return localName;
}
/**
* Gets the foreign name.
*
* @return the foreign name
*/
public String getForeignName()
{
return foreignName;
}
/**
* Indicates if the local name is the '*' constant.
*
* @return <code>true</code> if the local name is the '*' constant,
* <code>false</code> if not.
*/
public boolean isLocalNameStart()
{
return STAR_STRING.equals( localName );
}
/**
* Indicates if the foreign name is the '*' constant.
*
* @return <code>true</code> if the foreign name is the '*' constant,
* <code>false</code> if not.
*/
public boolean isLocalForeignStart()
{
return STAR_STRING.equals( foreignName );
}
/**
* Sets the type.
*
* @param type the type
*/
public void setType( OlcRwmMapValueTypeEnum type )
{
this.type = type;
}
/**
* Sets the local name.
*
* @param localName the local name
*/
public void setLocalName( String localName )
{
this.localName = localName;
}
/**
* Sets the foreign name.
*
* @param foreignName the foreign name
*/
public void setForeignName( String foreignName )
{
this.foreignName = foreignName;
}
/**
* {@inheritDoc}
*/
public String toString()
{
StringBuilder sb = new StringBuilder();
// Type
sb.append( type );
// Local Name
if ( ( localName != null ) && ( localName.length() > 0 ) )
{
sb.append( ' ' );
sb.append( localName );
}
// Foreign Name
if ( ( foreignName != null ) && ( foreignName.length() > 0 ) )
{
sb.append( ' ' );
sb.append( foreignName );
}
return sb.toString();
}
/**
* Parses a OlcValSortValue value.
*
* @param s
* the string to be parsed
* @return the associated OlcValSortValue object
* @throws ParseException
* if there are any recognition errors (bad syntax)
*/
public static synchronized OlcRwmMapValue parse( String s ) throws ParseException
{
if ( s == null )
{
return null;
}
// Trimming the value
s = Strings.trim( s );
// Getting the chars of the string
char[] chars = new char[s.length()];
s.getChars( 0, s.length(), chars, 0 );
// Creating the position
Position pos = new Position();
pos.start = 0;
pos.end = 0;
pos.length = chars.length;
return parseInternal( chars, pos );
}
/**
* Parses the given string.
*
* @param chars the characters
* @param pos the position
* @return the associated OlcValSortValue object
* @throws ParseException
*/
private static OlcRwmMapValue parseInternal( char[] chars, Position pos ) throws ParseException
{
OlcRwmMapValue value = new OlcRwmMapValue();
// Empty (trimmed) string?
if ( chars.length == 0 )
{
return null;
}
do
{
// Type
String typeString = getQuotedOrNotQuotedOptionValue( chars, pos );
if ( ( typeString != null ) && ( !typeString.isEmpty() ) )
{
OlcRwmMapValueTypeEnum type = OlcRwmMapValueTypeEnum.fromString( typeString );
if ( type != null )
{
value.setType( type );
}
else
{
throw new ParseException( "Could not identify keyword '" + typeString
+ "' as a valid type.", pos.start );
}
}
else
{
throw new ParseException( "Could not find the 'type' value", pos.start );
}
// First Name
String firstName = getQuotedOrNotQuotedOptionValue( chars, pos );
if ( ( firstName == null ) || ( firstName.isEmpty() ) )
{
throw new ParseException( "Could not find any 'localName' or 'foreignName' value", pos.start );
}
// Second Name
String secondName = getQuotedOrNotQuotedOptionValue( chars, pos );
if ( ( secondName == null ) || ( secondName.isEmpty() ) )
{
// Local Name is optional
// If we got only one name, it's the foreign name
value.setForeignName( firstName );
}
else
{
value.setLocalName( firstName );
value.setForeignName( secondName );
}
}
while ( ( pos.start != pos.length ) && ( ( Strings.charAt( chars, pos.start ) ) != '\0' ) );
return value;
}
private static String getQuotedOrNotQuotedOptionValue( char[] chars, Position pos ) throws ParseException
{
if ( pos.start != pos.length )
{
char quoteChar = '\0';
boolean isInQuotes = false;
char c = Strings.charAt( chars, pos.start );
char[] v = new char[chars.length - pos.start];
int current = 0;
do
{
if ( ( current == 0 ) && !isInQuotes )
{
// Whitespace
if ( Character.isWhitespace( c ) )
{
// We ignore all whitespaces until we find the start of the value
pos.start++;
continue;
}
// Double quotes (") or single quotes (')
else if ( ( c == '"' ) || ( c == '\'' ) )
{
isInQuotes = true;
quoteChar = c;
pos.start++;
continue;
}
// Any other char is part of a value
else
{
v[current++] = c;
pos.start++;
}
}
else
{
if ( isInQuotes )
{
// Double quotes (") or single quotes (')
if ( quoteChar == c )
{
isInQuotes = false;
pos.start++;
continue;
}
// Checking for escaped quotes
else if ( c == '\\' )
{
// Double quotes (")
if ( ( quoteChar == '"' ) && ( Strings.areEquals( chars, pos.start, "\\\"" ) >= 0 ) )
{
v[current++] = '"';
pos.start += 2;
continue;
}
// Single quotes (')
else if ( ( quoteChar == '\'' ) && ( Strings.areEquals( chars, pos.start, "\\'" ) >= 0 ) )
{
v[current++] = '\'';
pos.start += 2;
continue;
}
}
// Any other char is part of a value
else
{
v[current++] = c;
pos.start++;
}
}
else
{
// Whitespace
if ( Character.isWhitespace( c ) )
{
// Once we have found the start of the value, the first whitespace is the exit
break;
}
// Any other char is part of a value
else
{
v[current++] = c;
pos.start++;
}
}
}
}
while ( ( c = Strings.charAt( chars, pos.start ) ) != '\0' );
// Checking the resulting value
if ( current == 0 )
{
throw new ParseException( "Couldn't find a value.", pos.start );
}
char[] value = new char[current];
System.arraycopy( v, 0, value, 0, current );
// Getting the value as a String
return new String( value );
}
return null;
}
}