All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.okapi.lib.xliff2.validation.Validation Maven / Gradle / Ivy

There is a newer version: 1.47.0
Show newest version
/*===========================================================================
  Copyright (C) 2014-2017 by the Okapi Framework contributors
-----------------------------------------------------------------------------
  Licensed 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 net.sf.okapi.lib.xliff2.validation;

import java.text.Normalizer;
import java.text.Normalizer.Form;
import java.util.ArrayList;
import java.util.List;

import net.sf.okapi.lib.xliff2.core.BaseList;
import net.sf.okapi.lib.xliff2.core.ExtAttributes;
import net.sf.okapi.lib.xliff2.core.IWithExtAttributes;
import net.sf.okapi.lib.xliff2.core.Unit;
import net.sf.okapi.lib.xliff2.validation.Rule.Type;

/**
 * Represents the <validation> element of the 
 * Validation module.
 */
public class Validation extends BaseList implements IWithExtAttributes {

	private ExtAttributes xattrs;
	private int declarationCount;

	/**
	 * Creates an empty {@link Validation} object.
	 */
	public Validation () {
		// Nothing to set
	}
	
	/**
	 * Copy constructor.
	 * @param original the original object to duplicate.
	 * @param markAsInherited true to mark all rules in the clone as inherited, false to leave them as they are.
	 */
	public Validation (Validation original,
		boolean markAsInherited)
	{
		super(original);
		// Fields specific to this class
		if ( original.hasExtAttribute() ) {
			xattrs = new ExtAttributes(original.xattrs);
		}
		// if need marker rules as inherited
		for ( Rule rule : this ) {
			rule.setInherited(true);
		}
	}
	
	@Override
	public void setExtAttributes (ExtAttributes attributes) {
		this.xattrs = attributes;
	}

	@Override
	public ExtAttributes getExtAttributes () {
		if ( xattrs == null ) {
			xattrs = new ExtAttributes();
		}
		return xattrs;
	}

	@Override
	public boolean hasExtAttribute () {
		if ( xattrs == null ) return false;
		return !xattrs.isEmpty();
	}

	@Override
	public String getExtAttributeValue (String namespaceURI,
		String localName)
	{
		if ( xattrs == null ) return null;
		return xattrs.getAttributeValue(namespaceURI, localName);
	}

	/**
	 * Indicates if this list of rules has at least one that is not inherited.
	 * @return true if there is one or more non=inherited rule, false otherwise.
	 */
	public boolean hasNonInheritedRule () {
		for ( Rule rule : this ) {
			if ( !rule.isInherited() ) return true;
		}
		return false;
	}

	/**
	 * Prepare the rules for performing the validation tasks.
	 * You must call this method before calling {@link #processRules(Unit, String)}.
	 */
	public void prepare () {
		for ( Rule rule : this ) {
			rule.prepare();
		}
	}

	/**
	 * Applies the rules of this object on a given unit.
	 * You must call {@link #prepare()} before calling this method (if a rule has changed
	 * since the last call).
	 * @param unit the unit to validate.
	 * @param fileId the id of the file of the unit.
	 * @return null if no rule was processed or a list of issues that may be empty.
	 */
	public List processRules (Unit unit,
		String fileId)
	{
		List issues = new ArrayList<>();
		// Validation rules apply to the full content of the unit
		String target = unit.getPlainText(true, false);
		String source = null; // If needed only
		String unitId = unit.getId();
		int ruleCount = 0;

		// Process the rules
		for ( Rule rule : this ) {
			
			if ( !rule.isEnabled() ) continue;
			if ( rule.getType() == Type.CUSTOM ) continue;
			ruleCount++;
			
			// Else: apply the rule
			String effectiveText = applyOptions(target, rule);
			
			String tmp;
			switch ( rule.getType() ) {
			case ENDSWITH:
				if ( !effectiveText.endsWith(rule.getEffectiveData()) ) {
					// Not ending the target
					issues.add(new Issue(fileId, unitId, "endsWith",
						String.format("Target does not ends with '%s'", rule.getEffectiveData()),
						rule.getDisplay()));
					continue;
				}
				break;
			
			case ISNOTPRESENT:
				if (effectiveText.contains(rule.getEffectiveData())) {
					// Present at least once in target
					issues.add(new Issue(fileId, unitId, "isNotPresent",
						String.format("The text '%s' is present in the target", rule.getEffectiveData()),
						rule.getDisplay()));
					continue;
				}
				break;
			
			case ISPRESENT:
				int count = 0;
				tmp = effectiveText;
				int n = tmp.indexOf(rule.getEffectiveData());
				while ( n > -1 ) {
					tmp = tmp.replace(rule.getEffectiveData(), "");
					count++;
					n = tmp.indexOf(rule.getEffectiveData());
				}
				if ( rule.getExistsInSource() ) {
					if ( source == null ) {
						source = unit.getPlainText(false, false);
					}
					String src = applyOptions(source, rule);
					if (!src.contains(rule.getEffectiveData())) {
						// Not present in source
						issues.add(new Issue(fileId, unitId, "isPresent-NotInSource",
							String.format("The text '%s' is not present in the source", rule.getEffectiveData()),
							rule.getDisplay()));
						continue;
					}
				}
				if ( rule.getOccurs() == 0 ) {
					if ( count < 1 ) {
						// Not present at least 1 time in target
						issues.add(new Issue(fileId, unitId, "isPresent-NotInTarget",
							String.format("The text '%s' is not present in the target", rule.getEffectiveData()),
							rule.getDisplay()));
						continue;
					}
				}
				else {
					if ( rule.getOccurs() != count ) {
						// Not present exactly N times in target
						issues.add(new Issue(fileId, unitId, "isPresent-WrongCount",
							String.format("Occurences of text '%s' the target: %d, expected: %d",
								rule.getEffectiveData(), count, rule.getOccurs()), rule.getDisplay()));
						continue;
					}
				}
				break;
			
			case STARTSWITH:
				if ( !effectiveText.startsWith(rule.getEffectiveData()) ) {
					// Not starting the target
					issues.add(new Issue(fileId, unitId, "startsWith",
						String.format("Target does not starts with '%s'.", rule.getEffectiveData()),
						rule.getDisplay()));
					continue;
				}
				break;
				
			case CUSTOM:
				// Do nothing
				break;
			}
		}
		
		// Return null or the array
		if ( ruleCount == 0 ) return null; // No rule processed
		return issues; // May be empty if no issue was detected
	}
	
	private String applyOptions (String text,
		Rule rule)
	{
		String effectiveText = text;
		if ( !rule.isCaseSensitive() ) effectiveText = effectiveText.toLowerCase();
		switch ( rule.getNormalization() ) {
		case NFC:
			effectiveText = Normalizer.normalize(effectiveText, Form.NFC);
			break;
		case NFD:
			effectiveText = Normalizer.normalize(effectiveText, Form.NFD);
			break;
		case NONE:
			// Do nothing
			break;
		}
		return effectiveText;
	}
	
	public int getDeclarationCount () {
		return declarationCount;
	}

	public void addDeclaration () {
		this.declarationCount++;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy